We will use the Phylonco project as an example, to learn how to create the Java classes and module to extend LPhy and LPhyBEAST.
The extension “phylonco-lphy”
To create a LPhy extension, first you need to write your own classes to extend or implement the extensible components defined from the core. At the time of writing, LPhy makes three components extensible:
It is a Java interface to represent all types of generative distributions, such as probability distributions, tree generative distributions (e.g. Birth-death, Coalescent), and PhyloCTMC generative distributions.
It is an abstract class to represent all functions in LPhy language.
The container provider class
The second step is to register your extended or implemented Java classes into the extension mechanism.
This will involve two files:
There is an extra provider configuration file located under the
resources subfolder for Java 1.8 only.
As you can see in Figure 1,
phylonco.lphy.spi.Phylonco is a container class
to provide services defined in the service provider interface (SPI),
which lists all extended classes in the extension.
It is also a service provider class, hence a public no-args constructor is required.
Here we create a new concept, called as
container provider class,
to collect all extended classes in one class,
so that we can avoid to create a no-args constructor for every classes.
When you create an extension, you need to give a sensible name to
the container provider class in your extension,
and place it into a package having the name similar to
Then, the line pointed by a red arrow in
declares the service provider class
Here SPI is the Java interface
The 3rd file named as
lphy.spi.LPhyExtension in the subfolder
is the provider configuration file used to register the
service provider in Java 1.8.
This allows the LPhy and its extensions to be able to integrate with the non-module system,
such as BEAST 2 and its packages.
This file name is same as the SPI file name concatenated with its package, which is required by the mechanism.
Please note the recommended LPhy extension mechanism is using the Java module system
and configuring the SPI and providers in the
which is a different mechanism comparing with the provider configuration file under the resources subfolder.
Following Java package naming conventions
is critical. Though we are using the module system to avoid namespace collision,
it’d better to always name your Java package by starting with your extension name,
but not the reserved core name, such as lphy, lphybeast, beast, etc.
For example, here we have the package
phylonco.lphy.evolution to contain the extended LPhy data types and models.
phylonco.lphy.spi includes the container provider class.
The extension “phylonco-lphybeast”
To create a LPhyBEAST extension, first you need to write your own mapping classes to implement the interface ValueToBEAST and GeneratorToBEAST. The former maps a LPhy Value object to a BEASTInterface, the latter maps a LPhy Generator to a BEASTInterface.
Registering mapping classes
Then these mapping classes will be registered in a register class which has to implement the interface
This is similar to SPI, but is modified to use BEAST 2 class loader instead of
The right side of Figure 2 shows the example of registering mapping classes
in the extension “phylonco-lphybeast”. On the bottom of the register class, there are two lists
to exclude the Value and Generator existing in LPhy, but cannot or do not need to create the mapping class
to map the BEASTInterface in BEAST 2. Otherwise, the validation process may throw
Because LPhy and BEAST 2 are not using the same classes for sequence types, you need to link them in the register class as well.
LPhyBEAST is also a BEAST 2 extension
As well as it is an extension of LPhyBEAST, phylonco-lphybeast is an extension of BEAST 2.
version.xml has to be used to declare the BEAST 2 package dependencies.
The example code is below:
<addon name='phylonco' version='0.0.6'> <depends on='beast2' atleast='2.6.6'/> <depends on='BEASTLabs' atleast='1.9.7'/> <depends on='lphybeast' atleast='0.3.0'/> </addon>