---
title: "R6 Generator Maven Plugin: Metadata and Maven configuration"
author: "Rob Challen"
date: "26/10/2020"
output: 
  html_vignette
header-includes:
  \usepackage{amsmath}
  \usepackage{minted}
  \usemintedstyle{emacs}
  \setminted[java]{fontsize=\footnotesize,tabsize=3}
  \setminted[xml]{fontsize=\footnotesize,tabsize=3}
vignette: >
  %\VignetteIndexEntry{R6 Generator Maven Plugin: Metadata and Maven configuration}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(tidyverse)
here::i_am("vignettes/R6-generator-maven-config.Rmd")
source(here::here("vignettes/codeSnip.R"))
```

<div class="watermark">DRAFT</div>

## Maven `pom.xml` options

An example of the Maven configuration from this test project is shown below. The
key parts of this configuration are described below:

* Dependency on the `r6-generator-runtime` Java library.
* Github Maven repository declarations for both code and plugins.
* Plugin configuration for the `r6-generator-maven-plugin`.

### Sample `pom.xml`

```{r results='asis', echo = FALSE}
codeSnip(type="xml",filename=here::here("java/pom.xml"))
```

## The r6-generator-runtime Java library

The `runtime` Java library contains code needed in the development of R
compatible libraries in Java. These are the annotations that identify a Java
Class as part of the R Api, (`uk.co.terminological.rjava.RClass` and
`uk.co.terminological.rjava.RMethod`), specialised data types that can be round
tripped between R and Java (in package `uk.co.terminological.rjava.types.*`),
and various data conversion helpers (e.g.
`uk.co.terminological.rjava.RConverter`) which can be used to accelerate
development of an R centric API in Java.

## Github maven repository declarations for both code and plugins

Both the core maven plugin and the `runtime` library are available through the
the Maven central repository. The `${r6.version}` property is here set to
`xx.xx.xx-SNAPSHOT` which retrieves the development version of the plugin. or
could be `1.0` for stable versions. The most recent stable release version
numbers will be available [on the github releases
page](https://github.com/terminological/r6-generator/tags) or [on maven
central](https://central.sonatype.com/artifact/io.github.terminological/r6-generator).

Unstable releases are managed on Github packages. Use of Github SNAPSHOT releases 
is only possible if you have set up a Github personal access token (classic). This process is 
[described here](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) 
and your personal tokens can be set up [here](https://github.com/settings/tokens). 
For package read access ticking the box for `read:packages` is sufficient. The
token generated must then be copied into your `~/.m2/settings.xml` to allow
Maven to pick up the SNAPSHOTs. It is generally easier to just use Maven central
releases.

## Plugin configuration for the r6-generator-maven-plugin

### outputDirectory

The plugin needs to know where to output the R library. In the example above
this is `<outputDirectory>${project.basedir}/..</outputDirectory>` which
specifies the generated R package will reside in the directory above the java
`pom.xml`. This infers that your Java code should be in a subdirectory of the R
project (and hence the root of the Git repository). We recommend using the
`java` directory for this. Keeping the Java source code within the R project is
the best option as the resulting R package can be committed to GitHub with the
Java source in the `java` directory (which is where R CMD Check expects sources
to be). This may however be impossible if the Java library requires that is in
the root of the github project. In this case the R and Java code can co-exist,
and the `pom.xml` can be in the project root. This will be OK however if you
plan on submitting your library to CRAN it will generate a few NOTES that will
need to be explained.

If the R package is generated in a sub-directory of the Java code this has
implications for the ability to compile that code from source from within R, and
is generally a bad idea. In this case the fat JAR must be distributed with the R
package and the fact that the R package is in a sub-directory will need to be be
specified if the library is intended to be installed via GitHub (e.g. using
`devtools::install_github("my-org/my-project")`. It is also equally possible to
place the generated code into the root directory of the project
(`${project.basedir}`) or indeed into a completely separate directory.

### packageData

The package data section includes metadata that describes the R library and a few control flags:

* `title`
  + the title is used in description files and man pages
* `version` (optional - defaults to `${package.version}`)
  + the version of the R package that will be generated. This can be either
  specified as a Java/Maven style semantic version (e.g. `xx.xx.xx-SNAPSHOT` by
  reusing the Maven `${package.version}`) or an R style version
  (`yy.yy.yy.9000`). If given as a Java/Maven style `-SNAPSHOT` version the
  generated R package will be one patch version less - so `1.0.0-SNAPSHOT` will
  generate an R package with version `0.99.99.9000`. This is to maintain
  consistent ordering between the two versioning styles when you are syncing the
  R package to Maven versions.
* `debug` (optional - defaults to `false`)
  + a `true` or `false` value that determines whether remote java debugging
  should be compiled into the R package. Remote debugging affects performance
  and can prevent the loading of the R package if previous versions have not
  been unload correctly. This is useful only for debugging R to Java integration
  problems.
* `usePkgdown` (optional - defaults to `false`)
  + If the generated R package is working and loads correctly we can use `r
  cran("pkgdown")` to generate online documentation. This will be generated in a
  `docs` sub-folder of the project `outputDirectory`. This can be pushed to
  GitHub and used as online documentation of the generated R library. Regardless
  of online documentation, the standard R `man` pages are generated for
  interactive help on the package. Pkgdown documentation will not be generated
  if the project is in debug mode.
* `useRoxygen2` (optional - defaults to `false`)
  + If the generated R package is working and loads correctly we can use 
  `r cran("devtools")` to generate configuration files and man pages for the
  package using Roxygen2 annotations. This also allows co-existence of manually
  written and generated functions, within the same package. This is a fairly
  experimental feature and I can't promise that generated code will not
  accidentally over-write manually written code. Use it at your own risk.
* `useJavadoc` (optional - defaults to `false`)
  + Along side the R documentation it may be helpful to provide Javadocs of the
  Java back end of the library. These are generated into the `docs\javadoc`
  sub-folder.
* `installLocal` (optional - defaults to `false`)
  + If building the R package is successful maven will try and use 
  `pak::local_install` to install it and any dependencies on the local machine.
  This is useful during development as it gets around some of the potential
  version inconsistencies that crop up during iterative development. It is not 
  intended for use outside of development e.g. in a CI environment.
* `precompileBinary` (defaults to `true`)
  + Usually we wish to distribute a package with a compiled jar file of the Java
  code. In exceptional circumstances this can be replaced with a sources only
  distribution. In this case the Java code will be compiled on first use on the
  users machine, which should be done automatically. To make this possible the
  user must have a Java development kit installed.
* `packageAllDependencies` (defaults to `true`, only relevant if `precompileBinary` is true)
  + A single jar file is created including all dependencies in one "uber-jar".
  This is the most reliable option but transitive dependencies result in large
  Java libraries which will almost always exceed CRAN's stringent 4Mb limits.
  This limit is not an issue if you plan on deploying to `r-universe`,
  which is how I package my projects. If this option is set to false then the
  resulting jar file will need to fetch dependencies from the internet on first
  use. This can be time consuming and a potential point of failure.
* `useShadePlugin` (defaults to `false`, only relevant if `packageAllDependencies` is true)
  + The Maven shade plugin can be used to minimise the size of a "uber-jar" but
  sometimes removes essential pieces. This could work to reduce the size of a
  packaged jar file but thorough testing of the result is recommended.
* `rjavaOpts\rjavaOpt`
  + A list of JVM flags can be provided that will be provided during the
  initialization of the Java Virtual Machine (JVM). In the example here the JVM
  is given 256Mb of heap space (`-Xmx256M`). Only one JVM is initialised
  regardless of how many different Java based R packages are used, and only the
  first one gets to decide the initial parameters. As such these options may be
  ignored by R if a JVM has already been created. Javadoc documentation will not
  be generated if the project is in debug mode.
* `packageName`
  + the most important entry - the desired name of the package forms the name
  space for the package so it is best that it is short and has not already been
  used for a R package - e.g. don't call it "stats".
* `license`
  + a license specification - it is best to use a [CRAN friendly
  license](https://cran.r-project.org/web/licenses/). N.B. This should be `MIT`
  rather than `MIT + file LICENSE`, the additional license file is added if
  needed.
* `maintainerName`, `maintainerFamilyName`, `maintainerEmail`, `maintainerOrganisation`
  + the author details used here are supplemented by any author details found in
  `@Author` Java doclet tags in the code. 

## Goals

The plugin has three goals - `clean-r-library`, `flatten-pom` and `generate-r-library`

* `clean-r-library` (binds to Maven clean phase)
  + clear out old generated files leaving user modified files in place.
* `flatten-pom` (binds to Maven process resources phase)
  + create a simplified pom, collapsing any details inherited from parent pom and
  removing dependencies on parent poms
* `generate-r-library` (binds to Maven install phase)
  + run the code generator and install compiled jar into the R package.

In general all 3 goals should be run.
