Allow alabaster applications to specify an alternative loading function in altLoadObject.

altLoadObject(...)

altLoadObjectFunction(load)

Arguments

...

Further arguments to pass to loadObject or its equivalent.

load

Function that can serve as a drop-in replacement for loadObject.

Value

For altLoadObject, any R object similar to those returned by loadObject.

For altLoadObjectFunction, the alternative function (if any) is returned if load is missing. If load is provided, it is used to define the alternative, and the previous alternative is returned.

Details

altLoadObject is just a wrapper around loadObject that responds to any setting of altLoadObjectFunction. This allows alabaster applications to inject customizations into the loading process, e.g., to add more metadata to particular objects. Developers of alabaster extensions should use altLoadObject (instead of loadObject) to load child objects when writing their own loading functions, to ensure that application-specific customizations are respected for the children.

To motivate the use of altLoadObject, consider the following scenario.

  1. We have created a loading function loadX function to load an instance of class X in an alabaster extension. This function may be called by loadObject if instances of X are children of other objects.

  2. An alabaster application Y requires the addition of some custom metadata during the loading process for X. It defines an alternative loading function loadObject2 that, upon encountering a schema for X, redirects to a application-specific loader loadX2. An example implementation for loadX2 would involve calling loadX and decorating the result with the extra metadata.

  3. When operating in the context of application Y, the loadObject2 generic is used to set altLoadObjectFunction. Any calls to altLoadObject in Y's context will subsequently call loadObject2.

  4. So, when writing a loading function in an alabaster extension for a class that might contain X as children, we use altLoadObject instead of directly using loadObject. This ensures that, if a child instance of X is encountered and we are operating in the context of application Y, we correctly call loadObject2 and then ultimately loadX2.

Note for application developers: loadX2 should not call altLoadObject on the same instance of X. Doing so will introduce an infinite recursion where altLoadObject calls loadX2 that then calls altLoadObject, etc. Rather, application developers should either call loadObject or loadX directly. For child objects, no infinite recursion will occur and either loadObject2 or altLoadObject can be used.

Author

Aaron Lun

Examples

old <- altLoadObjectFunction()

# Setting it to something.
altLoadObjectFunction(function(...) {
    print("YAY")
    loadObject(...) 
})

# Staging an example DataFrame:
library(S4Vectors)
df <- DataFrame(A=1:10, B=LETTERS[1:10])
tmp <- tempfile()
dir.create(tmp)
out <- stageObject(df, tmp, path="coldata")

# And now loading it - this should print our message.
altLoadObject(out, tmp)
#> [1] "YAY"
#> DataFrame with 10 rows and 2 columns
#>            A           B
#>    <integer> <character>
#> 1          1           A
#> 2          2           B
#> 3          3           C
#> 4          4           D
#> 5          5           E
#> 6          6           F
#> 7          7           G
#> 8          8           H
#> 9          9           I
#> 10        10           J

# Restoring the old loader:
altLoadObjectFunction(old)