---
title: "Implementing custom iSEEindex resources"
author: 
  - name: Kevin Rue-Albrecht
    affiliation:
    - University of Oxford
    email: kevin.rue-albrecht@imm.ox.ac.uk
output: 
  BiocStyle::html_document:
    self_contained: yes
    toc: true
    toc_float: true
    toc_depth: 2
    code_folding: show
date: "`r doc_date()`"
package: "`r pkg_ver('iSEEindex')`"
vignette: >
  %\VignetteIndexEntry{Implementing custom iSEEindex resources}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}  
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(
    collapse = TRUE,
    comment = "#>",
    crop = NULL ## Related to https://stat.ethz.ch/pipermail/bioc-devel/2020-April/016656.html
)
```

```{r, eval=!exists("SCREENSHOT"), include=FALSE}
SCREENSHOT <- function(x, ...) knitr::include_graphics(x)
```

```{r vignetteSetup, echo=FALSE, message=FALSE, warning = FALSE}
## Track time spent on making the vignette
startTime <- Sys.time()

## Bib setup
library("RefManageR")

## Write bibliography information
bib <- c(
    R = citation(),
    BiocStyle = citation("BiocStyle")[1],
    knitr = citation("knitr")[1],
    RefManageR = citation("RefManageR")[1],
    rmarkdown = citation("rmarkdown")[1],
    sessioninfo = citation("sessioninfo")[1],
    testthat = citation("testthat")[1],
    iSEEindex = citation("iSEEindex")[1]
)
```

# iSEEindex resources

## Overview

`r Biocpkg("iSEEindex")` imports data sets and initial app configurations from files.
Each of those files is represented by a Uniform Resource Identifier (URI) in the lists of metadata returned by the functions supplied to the `FUN.datasets` and `FUN.initial` arguments of `iSEEindex()`.

`r Biocpkg("iSEEindex")` requires each URI to contain a scheme component ([Wikipedia][scheme-wikipedia] `r fontawesome::fa("external-link")`), to identify the type of resource and invoke the associated method for accessing it.

This system allows `r Biocpkg("iSEEindex")` users to use both standard and custom schemes in the URI of their resources, to fetch files from virtually any logical or physical resource, local or remote.

In this vignette, we describe the implementation of `r Biocpkg("iSEEindex")` resources, using built-in classes of resources as examples.


## Implementation

Given a scheme `<scheme>`, `r Biocpkg("iSEEindex")` automatically attempts to create an object of class `iSEEindex<Scheme>Resource` that contains the class `iSEEindexResource`.
For instance, the scheme `https` produces an object of class `iSEEindexHttpsResource`.

`r Biocpkg("iSEEindex")` provides a range of built-in `iSEEindexResource` sub-classes, described in [dedicated sections below](#builtin).

The raw value of the URI (including the scheme component) is always stored in the `uri` slot of the `iSEEindexResource` object.

Each `iSEEindexResource` sub-class must define the method `precache()`.

On first use, `precache()` processes the raw value of the URI, downloads the resource file locally using custom code if necessary, caches the file using `r Biocpkg("BiocFileCache")`, and returns the path to the cached file.

In subsequent uses, `r Biocpkg("BiocFileCache")` is used to fetch the cached file directly.

# Built-in resources {#builtin}

## iSEEindexHttpsResource

This type of resource is documented in `help("iSEEindexHttpsResource-class")`.

### Structure

Briefly, this class is used to represent files that are publicly accessible online over HTTPS.

The URI must use the standard scheme "https", followed by the URI to the file on the internet.

Example:

```bash
https://zenodo.org/record/7304331/files/ReprocessedAllenData.rds?download=1
```


### Caching

The `r Biocpkg("BiocFileCache")` package can handle HTTPS perfectly well.

In this instance, the `precache()` function has no other job than to cache the file located at the given URI using `r Biocpkg("BiocFileCache")`.


## iSEEindexLocalhostResource

### Structure

This type of resource is documented in `help("iSEEindexLocalhostResource-class")`.

Briefly, this class is used to represent files that are already present on the filesystem of the machine that runs the application.

The URI must use the custom scheme "localhost", followed by the path -- absolute or relative -- to the file on disk.

Example:

```bash
localhost:///absolute/path/to/file
localhost://relative/path/to/file
```

### Caching

Now, while the `r Biocpkg("BiocFileCache")` package can perfectly well handle local files, it does not know how to deal with the custom scheme `localhost`.

In this instance, the `precache()` function has for only job to remove the `localhost://` prefix from the URI, and cache the file located at the resulting file path using `r Biocpkg("BiocFileCache")`.


## iSEEindexRcallResource

### Structure

This type of resource is documented in `help("iSEEindexRcallResource-class")`.

Briefly, this class is used to represent files whose local file path is obtained as the result of executing R code.

The URI must use the custom scheme "rcall", followed by the R code to execute.

This custom scheme was created mainly to dynamically fetch the example files distributed and installed with the package.

Example:

```bash
rcall://system.file(package='iSEEindex','ReprocessedAllenData_config_01.R')
```

### Caching

The custom scheme `rcall` is entirely made up for the purpose described here; it is not in any way recognised as a standard scheme by the [Internet Assigned Numbers Authority (IANA)][iana-uri].
As such, the `r Biocpkg("BiocFileCache")` package cannot possibly know how to handle that custom scheme.

In this instance, the `precache()` function has the job to remove the `rcall://` prefix from the URI, evaluate the remainder of the URI as R code, and cache the file located at the resulting file path using `r Biocpkg("BiocFileCache")`.


## iSEEindexS3Resource

### Structure

This type of resource is documented in `help("iSEEindexS3Resource-class")`.

Briefly, this class is used to represent files that are accessible from [Amazon S3][amazon-s3].

The URI must use the custom scheme "s3", followed by the S3 URI to the file.

Example:

```bash
s3://bucket/prefix/file
```

### Caching

Now, while the scheme `s3` is recognised by the [AWS Command Line Interface][aws-cli], the `r Biocpkg("BiocFileCache")` package does not know how to deal with it.

In this instance, the `precache()` function has the job to parse the URI for information that is passed to the `r BiocStyle::CRANpkg("paws.storage")` package to download the file, which is then cached using `r Biocpkg("BiocFileCache")`.


# Reproducibility

The `r Biocpkg("iSEEindex")` package `r Citep(bib[["iSEEindex"]])` was made possible thanks to:

* R `r Citep(bib[["R"]])`
* `r Biocpkg("BiocStyle")` `r Citep(bib[["BiocStyle"]])`
* `r CRANpkg("knitr")` `r Citep(bib[["knitr"]])`
* `r CRANpkg("RefManageR")` `r Citep(bib[["RefManageR"]])`
* `r CRANpkg("rmarkdown")` `r Citep(bib[["rmarkdown"]])`
* `r CRANpkg("sessioninfo")` `r Citep(bib[["sessioninfo"]])`
* `r CRANpkg("testthat")` `r Citep(bib[["testthat"]])`

This package was developed using `r BiocStyle::Biocpkg("biocthis")`.


Code for creating the vignette

```{r createVignette, eval=FALSE}
## Create the vignette
library("rmarkdown")
system.time(render("resources.Rmd", "BiocStyle::html_document"))

## Extract the R code
library("knitr")
knit("resources.Rmd", tangle = TRUE)
```

Date the vignette was generated.

```{r reproduce1, echo=FALSE}
## Date the vignette was generated
Sys.time()
```

Wallclock time spent generating the vignette.

```{r reproduce2, echo=FALSE}
## Processing time in seconds
totalTime <- diff(c(startTime, Sys.time()))
round(totalTime, digits = 3)
```

`R` session information.

```{r reproduce3, echo=FALSE}
## Session info
library("sessioninfo")
options(width = 100)
session_info()
```



# Bibliography

This vignette was generated using `r Biocpkg("BiocStyle")` `r Citep(bib[["BiocStyle"]])`
with `r CRANpkg("knitr")` `r Citep(bib[["knitr"]])` and `r CRANpkg("rmarkdown")` `r Citep(bib[["rmarkdown"]])` running behind the scenes.

Citations made with `r CRANpkg("RefManageR")` `r Citep(bib[["RefManageR"]])`.

```{r vignetteBiblio, results = "asis", echo = FALSE, warning = FALSE, message = FALSE}
## Print bibliography
PrintBibliography(bib, .opts = list(hyperlink = "to.doc", style = "html"))
```

<!-- Links -->

[scheme-wikipedia]: https://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Syntax
[iana-uri]: https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml
[amazon-s3]: https://aws.amazon.com/s3/
[aws-cli]: https://aws.amazon.com/cli/
