Cache API calls locally

And do this by default. A problem is that the underlying R.cache
package does not provide an expiry mechanism.
To set up an ideal expiry mechanism, the KorAPConnection constructor
should be able to get some short information about API and index
version. This can be handled later, see 
https://github.com/KorAP/Krill/issues/62

Change-Id: Ia7a8d6f0800a67d3ab39f162444751e2818d29bd
diff --git a/R/KorAPConnection.R b/R/KorAPConnection.R
index c1c131e..7eface5 100644
--- a/R/KorAPConnection.R
+++ b/R/KorAPConnection.R
@@ -3,6 +3,7 @@
 #' \code{KorAPConnection} objects represent the connection to a KorAP server.
 #' New \code{KorAPConnection} objects can be created by \code{KorAPConnection()}.
 #'
+#' @import R.cache
 #' @import jsonlite
 #' @import utils
 #' @import methods
@@ -10,7 +11,7 @@
 #'
 
 #' @export
-KorAPConnection <- setClass("KorAPConnection", slots=c(KorAPUrl="character", apiVersion="character", apiUrl="character", userAgent="character", timeout="numeric", verbose="logical"))
+KorAPConnection <- setClass("KorAPConnection", slots=c(KorAPUrl="character", apiVersion="character", apiUrl="character", userAgent="character", timeout="numeric", verbose="logical", cache="logical"))
 
 #' @param .Object KorAPConnection object
 #' @param KorAPUrl the URL of the KorAP server instance you want to access.
@@ -19,6 +20,7 @@
 #' @param userAgent user agent string.
 #' @param timeout time out in seconds.
 #' @param verbose logical. Decides whether following operations will default to be verbose.
+#' @param cache logical. Decides if API calls are cached locally. You can clear the cache with \code{\link{clearCache}()}.
 #' @return \code{\link{KorAPConnection}} object that can be used e.g. with \code{\link{corpusQuery}}
 #'
 #' @examples
@@ -31,7 +33,7 @@
 #' @rdname KorAPConnection-class
 #' @export
 setMethod("initialize", "KorAPConnection",
-          function(.Object, KorAPUrl = "https://korap.ids-mannheim.de/", apiVersion = 'v1.0', apiUrl, userAgent = "R-KorAP-Client", timeout=10, verbose = FALSE) {
+          function(.Object, KorAPUrl = "https://korap.ids-mannheim.de/", apiVersion = 'v1.0', apiUrl, userAgent = "R-KorAP-Client", timeout=10, verbose = FALSE, cache = TRUE) {
             .Object <- callNextMethod()
             m <- regexpr("https?://[^?]+", KorAPUrl, perl = TRUE)
             .Object@KorAPUrl <- regmatches(KorAPUrl, m)
@@ -47,9 +49,15 @@
             .Object@userAgent = userAgent
             .Object@timeout = timeout
             .Object@verbose = verbose
+            .Object@cache = cache
             .Object
           })
 
+
+KorAPCacheSubDir <- function() {
+  paste0("RKorAPClient_", packageVersion("RKorAPClient"))
+}
+
 setGeneric("apiCall", function(kco, ...)  standardGeneric("apiCall") )
 
 #' @aliases apiCall
@@ -57,6 +65,12 @@
 #' @param kco KorAPConnection object
 #' @param url request url
 setMethod("apiCall", "KorAPConnection",  function(kco, url) {
+  if (kco@cache) {
+    parsed <- R.cache::loadCache(dir=KorAPCacheSubDir(), key=list(url))
+    if (!is.null(parsed)) {
+      return(parsed)
+    }
+  }
   resp <- GET(url, user_agent(kco@userAgent), timeout(kco@timeout))
   if (!http_type(resp) %in% c("application/json", "application/ld+json")) {
     stop("API did not return json", call. = FALSE)
@@ -74,9 +88,21 @@
                        message <- sprintf("%s: KorAP API request failed.", status_code(resp)))
     stop(message, call. = FALSE)
   }
+  if (kco@cache) {
+    R.cache::saveCache(parsed, key = list(url), dir = KorAPCacheSubDir(), compress = TRUE)
+  }
   parsed
 })
 
+setGeneric("clearCache", function(kco)  standardGeneric("clearCache") )
+
+#' @aliases clearCache
+#' @rdname KorAPConnection-class
+#' @export
+setMethod("clearCache", "KorAPConnection",  function(kco) {
+  R.cache::clearCache(dir=KorAPCacheSubDir())
+})
+
 #' @rdname KorAPConnection-class
 #' @param object KorAPConnection object
 #' @export