#' Extension generator abstract class
#'
#' @description
#' The mother class of all generators for biodb extension packages.
#'
#' @details
#' All generator classes for biodb extensions must inherit from this class.
#'
#' @examples
#' # Generate a new connector class inside the R folder:
#' pkgFolder <- file.path(tempfile(), 'biodbFoo')
#' dir.create(pkgFolder, recursive=TRUE)
#' biodb::ExtConnClass$new(path=pkgFolder, dbName='foo.db',
#' dbTitle='Foo database',
#' connType='mass', remote=TRUE)$generate()
#'
#' @import R6
#' @import chk
#' @export
ExtGenerator <- R6::R6Class('ExtGenerator',
public=list(
#' @description
#' Initializer.
#' @param path The path to the package folder.
#' @param loadCfg Set to FALSE to disable loading of tag values from config
#' file "biodb_ext.yml".
#' @param saveCfg Set to FALSE to disable saving of tag values into config
#' file "biodb_ext.yml".
#' @param pkgName The package name. If set to NULL, the folder name pointer by
#' the "path" paramater will be used as the package name.
#' @param pkgLicense The license of the package.
#' @param newPkg Set to TRUE if the package is not yet published on
#' Bioconductor.
#' @param email The email of the author.
#' @param firstname The firstname of the author.
#' @param lastname The lastname of the author.
#' @param dbName The name of the database (in biodb format "my.db.name"),
#' that will be used in "definitions.yml" file and for connector and entry
#' classes.
#' @param dbTitle The official name of the database (e.g.: HMDB, UniProtKB,
#' KEGG).
#' @param connType The type of connector class to implement.
#' @param entryType The type of entry class to implement.
#' @param makefile Set to TRUE if you want a Makefile to be generated.
#' @param travis Set to TRUE if you want a .travis.yml file to be generated.
#' @param remote Set to TRUE if the database to connect to is not local.
#' @param downloadable Set to TRUE if the database needs to be downloaded or
#' offers this possiblity.
#' @param editable Set to TRUE to allow the generated connector to create new
#' entries in memory.
#' @param writable Set to TRUE to enable the generated connector to write into
#' the database.
#' @param rcpp Set to TRUE to enable Rcpp C/C++ code inside the package.
#' @param vignetteName Set to the name of the default/main vignette.
#' @param githubRepos Set to the name of the associated GitHub repository.
#' Example: myaccount/myrepos.
#' @return Nothing.
#' @export
initialize=function(path, loadCfg=TRUE, saveCfg=TRUE, pkgName=getPkgName(path),
email='author@e.mail', dbName='foo.db', dbTitle='Foo database',
pkgLicense=getLicenses(), firstname='Firstname of author',
lastname='Lastname of author', newPkg=FALSE, connType=getConnTypes(),
entryType=getEntryTypes() , editable=FALSE, writable=FALSE, remote=FALSE,
downloadable=FALSE, makefile=FALSE, travis=FALSE, rcpp=FALSE,
vignetteName=getPkgName(path),
githubRepos=getReposName(path, default='myaccount/myrepos')) {
allParams <- as.list(environment())
explicitParams <- as.list(match.call())
chk::chk_string(path) # Path may not exist yet
private$path <- normalizePath(path, mustWork=FALSE) # Path may not exist yet
chk::chk_flag(loadCfg)
chk::chk_flag(saveCfg)
nonTags <- c('path', 'loadCfg', 'saveCfg')
# Load config
tags <- if (loadCfg) private$loadConfig() else list()
# Explicit parameters overwrite config
explicitParams[[1]] <- NULL # Remove function name
explicitParams[nonTags] <- NULL # Remove non-tag parameters
tags[names(explicitParams)] <- allParams[names(explicitParams)]
# Set fct default values
allParams[nonTags] <- NULL # Remove non-tag parameters
nonNullTags <- Filter(function(t) { return(! is.null(t)) }, tags)
allParams[names(allParams) %in% names(nonNullTags)] <- NULL
tags[names(allParams)] <- allParams
# Set tags
private$tags <- tags
# Check tags
private$checkTags()
# Save tags into config file
if (saveCfg)
private$saveConfig()
return(invisible(NULL))
}
#' @description
#' Generates the destination file(s).
#' @param overwrite If set to TRUE and destination files exist, overwrite the
#' destination files.
#' @param fail If set to FALSE, do not fail if destination files exist, just do
#' nothing and return.
#' @examples
#' # Generate a new extension package:
#' pkgFolder <- file.path(tempfile(), 'biodbFoo')
#' biodb::ExtPackage$new(pkgFolder)$generate()
,generate=function(overwrite=FALSE, fail=TRUE) {
private$doGenerate(overwrite=overwrite, fail=fail)
}
#' @description
#' Upgrade the destination file(s).
#' @param generate If set to FALSE, and destination file(s) do not exist, then
#' do not generate them.
,upgrade=function(generate=TRUE) {
private$doUpgrade(generate=generate)
}
),
private=list(
path=NULL
,loadCfg=NULL
,tags=NULL
,doGenerate=function(overwrite=FALSE, fail=TRUE) {
stop("Abstract method doGenerate() not implemented inside concrete class.")
}
,doUpgrade=function(generate=TRUE) {
stop("Abstract method doUpgrade() not implemented inside concrete class.")
}
,getCfgFile=function() {
return(file.path(private$path, "biodb_ext.yml"))
}
,getSubFolder=function(subpath, create=FALSE, exist=FALSE) {
# subpath: vector of subfolders
# create: if TRUE creates subfolders.
# exist: if TRUE fails if subfolders do not exist.
# Computes full path
s = do.call(file.path, as.list(c(private$path, subpath)))
# Tests if path exists
if (exist && ! dir.exists(s))
error('Path "', s, '" does not exist.')
# Creates path
if (create && ! dir.exists(s))
dir.create(s, recursive=TRUE)
return(s)
}
,subfolderContainsFiles=function(subpath, pattern) {
# subpath: vector of subfolders
# pattern: files to search (e.g.: '*.cpp')
s = private$getSubFolder(subpath)
return(dir.exists(s) && length(Sys.glob(file.path(s, pattern))) > 0)
}
,loadConfig=function() {
tags <- list()
cfgFile <- private$getCfgFile()
if (file.exists(cfgFile))
tags <- yaml::read_yaml(cfgFile)
return(tags)
}
,saveConfig=function() {
if ( ! dir.exists(private$path))
dir.create(private$path, recursive=TRUE)
yaml::write_yaml(private$tags, private$getCfgFile())
}
,checkTags=function() {
chk::chk_match(private$tags$pkgName, regexp="^biodb[A-Z][A-Za-z0-9]+$")
chk::chk_match(private$tags$email,
regexp="^[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+$")
chk::chk_string(private$tags$firstname)
chk::chk_string(private$tags$lastname)
chk::chk_match(private$tags$dbName, regexp="^[a-z0-9.]+$")
chk::chk_string(private$tags$dbTitle)
chk::chk_string(private$tags$vignetteName)
chk::chk_match(private$tags$githubRepos,
regexp="^[a-zA-Z0-9_-]+/[a-zA-Z0-9_-]+$")
chk::chk_flag(private$tags$newPkg)
chk::chk_flag(private$tags$makefile)
chk::chk_flag(private$tags$downloadable)
chk::chk_flag(private$tags$editable)
chk::chk_flag(private$tags$writable)
chk::chk_flag(private$tags$remote)
chk::chk_flag(private$tags$rcpp)
private$tags$connType <- match.arg(private$tags$connType, getConnTypes())
private$tags$entryType <- match.arg(private$tags$entryType, getEntryTypes())
private$tags$pkgLicense <- match.arg(private$tags$pkgLicense, getLicenses())
}
,createGenerator=function(cls, ...) {
# Add ellipsis
fields <- c(path=private$path, private$tags, list(...), loadCfg=FALSE,
saveCfg=FALSE)
# Call constructor
obj <- do.call(cls$new, fields)
return(obj)
}
))
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.