Extended Enums
The Java enum
concept is great for data that is constant and never changes.
However, sometimes there is a need for data that rarely changes, but sometimes does.
There is also a need for constants that can be extended by end-users.
The “Extended Enum” concept covers these use cases.
Strata includes the following extended enums (and many others):
BusinessDayConvention
DayCount
HolidayCalendar
RollConvention
IborIndex
OvernightIndex
FraConvention
FixedIborSwapConvention
Each extended enum consists of:
- an interface, which is the primary type used in the application
- one or more implementation classes, which may be package-scoped
- a helper class of constants, typically named as the plural form of the interface’s name
Using an Extended Enum
An extended enum instance is a normal Java class, and using it in application code is simple.
// find using the unique name
DayCount dayCount = DayCount.of("Act/365F");
// constants may be supplied for common names
DayCount dayCount = DayCounts.ACT_365F;
// a list of all names can also be obtained
Map<String,DayCount> dayCounts = DayCount.extendedEnum().lookupAll();
Once obtained, any method on the extended enum interface can be used.
Unique name
The key concept of an extended enum is that it has a unique name by which it is referred.
The instance of the extended enum may contain other state and methods but it can always be referred to by name.
As such, all extended enums implement the interface Named
.
The extended enum may be implemented using a Joda-Bean, however this is not required.
If it is, then the extended enum will implement the Joda-Convert annotations
@FromString
and @ToString
to ensure that when written to XML/JSON/Binary, only the string name is used.
Each extended enum is managed by a single instance of ExtendedEnum
.
The instance is typically defined as a private static constant.
Most extended enums will make the constant available via a static extendedEnum()
method.
Alternate names
In addition to the unique name, each extended enum instance may have zero to many alternate names. This can be used for backwards compatibility, where the unique name is changed. It can also be used where there is more than one name commonly used for the concept.
The standard of(String)
lookup method matches alternate names.
External names
Extended enums often refer to standard industry concepts. For example, the ISDA FpML specification includes long lists of standard codes for concepts such as day counts and indices. These external code lists can be tied to extended enums. When they are, the name used is called the external name.
For example, Strata includes external names that map the FpML names to the following extended enums:
BusinessDayConvention
DayCount
RollConvention
There may be multiple groups of external names to handle different external providers of data. For example, the mapping used by FpML may differ from that used by Bloomberg.
External names are made available via the static extendedEnum().externalNames(String group)
method.
The standard of(String)
lookup method does not match external names.
Adding or replacing Extended Enums
The key feature of extended enums is that application code can add to the known set, or replace the existing ones. This means that the definition of a holiday calendar supplied by Strata can be replaced if necessary.
It is intended that extended enums are known at system startup. While it is possible to add or replace instances after the system has started, doing so would require use of concurrent data structures that could slow the application down.
Ini files
Each extended enum is defined by one or more .ini
files.
The ini file must be located on the classpath in one of three specific locations.
- The “base” location is intended for use by Strata -
META-INF/com/opengamma/strata/config/base
. - The “library” location is intended for use by libraries that build on Strata -
META-INF/com/opengamma/strata/config/library
. - The “application” location is intended for use by end-user application code -
META-INF/com/opengamma/strata/config/application
.
The list of known locations can be expanded by setting the system property
com.opengamma.strata.config.directories
on the command line.
For example, if the extended enum interface is com.opengamma.strata.basics.date.DayCount
,
then an application ini file must be named: META-INF/com/opengamma/strata/config/application/DayCount.ini
.
The ResourceConfig
class
is responsible for loading and combining the ini files.
The ini file typically has the following format (described below):
[chain]
chainNextFile = false
[providers]
com.opengamma.strata.basics.date.StandardDayCounts = constants
com.opengamma.strata.basics.date.Business252DayCount = instance
[alternates]
Actual/Actual ISDA = Act/Act ISDA
[externals.FpML]
30/360 = 30/360 ISDA
Ini file chain
The list of known locations provides a deterministic ordering to the loading of ini files. The “base” location is lower priority than the “library” location which is lower priority than the “application” location. There must only ever be one ini file in each location on the classpath.
The [chain]
section is used to control how the files link together.
The chainNextFile
property is a boolean, “true” or “false”.
When processing more than one ini file, processing will continue to the next file if the flag is true,
and ignore lower priority files if the flag is false.
The default value for chainNextFile
is true, thus the whole [chain]
section is normally omitted.
Ini file providers
The extended enum instances are made available via providers defined in the [providers]
section.
Each entry in the section has a key=value
form, where the key is a full class name and the value is the provider type.
The three types of provider are:
constants
- the class contains public static final constants of the extended enum typelookup
- the class implementsNamedLookup
with a no-args constructorinstance
- the class has a static field namedINSTANCE
that is of typeNamedLookup
When initializing, the providers are loaded and used to find the extended enum instances.
In the example above, two providers are specified. Both are non-public classes.
StandardDayCounts
defines a set of public static final constants of type DayCount
.
Business252DayCount
defines public static final constant INSTANCE
of type NamedLookup<DayCount>
.
Both will be used to lookup extended enums.
Ini file alternate names
The [alternates]
section defines alternate names for the extended enum.
Each entry in the section has a key=value
form, where the key is the alternate name and the value is the unique name.
In the example above, the name “Actual/Actual ISDA” in FpML has the same meaning as the name “Act/Act ISDA” in Strata.
Ini file external names
The [externals.XXX]
section defines external names for the extended enum, where XXX
is the name of the group.
Each entry in the section has a key=value
form, where the key is the external name and the value is the unique name.
In the example above, the name “30/360” in FpML has the same meaning as the name “30/360 ISDA” in Strata.