X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/c65dfd0d76b9432b1ca305d2bf39d8bb309124a2..3e1c43866e5b523c3f1d273c25942ad56dc66d3f:/sdk/R/R/Collection.R diff --git a/sdk/R/R/Collection.R b/sdk/R/R/Collection.R index ca26082e07..fad452ac7a 100644 --- a/sdk/R/R/Collection.R +++ b/sdk/R/R/Collection.R @@ -1,201 +1,279 @@ source("./R/Subcollection.R") source("./R/ArvadosFile.R") -source("./R/HttpRequest.R") -source("./R/HttpParser.R") - -#' Arvados Collection Object +source("./R/RESTService.R") +source("./R/util.R") + +#' Collection +#' +#' Collection class provides interface for working with Arvados collections. +#' +#' @section Usage: +#' \preformatted{collection = Collection$new(arv, uuid)} +#' +#' @section Arguments: +#' \describe{ +#' \item{arv}{Arvados object.} +#' \item{uuid}{UUID of a collection.} +#' } +#' +#' @section Methods: +#' \describe{ +#' \item{add(content)}{Adds ArvadosFile or Subcollection specified by content to the collection.} +#' \item{create(fileNames, relativePath = "")}{Creates one or more ArvadosFiles and adds them to the collection at specified path.} +#' \item{remove(fileNames)}{Remove one or more files from the collection.} +#' \item{move(content, newLocation)}{Moves ArvadosFile or Subcollection to another location in the collection.} +#' \item{getFileListing()}{Returns collections file content as character vector.} +#' \item{get(relativePath)}{If relativePath is valid, returns ArvadosFile or Subcollection specified by relativePath, else returns NULL.} +#' } +#' +#' @name Collection +#' @examples +#' \dontrun{ +#' arv <- Arvados$new("your Arvados token", "example.arvadosapi.com") +#' collection <- Collection$new(arv, "uuid") +#' +#' newFile <- ArvadosFile$new("myFile") +#' collection$add(newFile, "myFolder") +#' +#' createdFiles <- collection$create(c("main.cpp", lib.dll), "cpp/src/") #' -#' Update description +#' collection$remove("location/to/my/file.cpp") #' -#' @examples arv = Collection$new(api, uuid) -#' @export Collection +#' collection$move("folder/file.cpp", "file.cpp") +#' +#' arvadosFile <- collection$get("location/to/my/file.cpp") +#' arvadosSubcollection <- collection$get("location/to/my/directory/") +#' } +NULL + +#' @export Collection <- R6::R6Class( "Collection", public = list( - api = NULL, - uuid = NULL, + uuid = NULL, + # api = NULL, - initialize = function(api, uuid) + initialize = function(api, uuid) { - self$api <- api - private$http <- HttpRequest$new() - private$httpParser <- HttpParser$new() + # self$api <- api + private$REST <- api$getRESTService() self$uuid <- uuid - collection <- self$api$getCollection(uuid) - private$fileContent <- private$getCollectionContent() + private$fileContent <- private$REST$getCollectionContent(uuid) private$tree <- CollectionTree$new(private$fileContent, self) }, add = function(content, relativePath = "") { - if(relativePath == "" || + if(is.null(private$tree)) + private$genereateCollectionTreeStructure() + + if(relativePath == "" || relativePath == "." || relativePath == "./") { - subcollection <- private$tree$.__enclos_env__$private$tree + subcollection <- private$tree$getTree() } else { - if(endsWith(relativePath, "/") && nchar(relativePath) > 0) - relativePath <- substr(relativePath, 1, nchar(relativePath) - 1) + relativePath <- trimFromEnd(relativePath, "/") + subcollection <- self$get(relativePath) + } + + if(is.null(subcollection)) + stop(paste("Subcollection", relativePath, "doesn't exist.")) + + if("ArvadosFile" %in% class(content) || + "Subcollection" %in% class(content)) + { + if(content$getName() == "") + stop("Content has invalid name.") + subcollection$add(content) + content + } + else + { + stop(paste0("Expected AravodsFile or Subcollection object, got ", + paste0("(", paste0(class(content), collapse = ", "), ")"), + ".")) + } + }, + + create = function(fileNames, relativePath = "") + { + if(is.null(private$tree)) + private$genereateCollectionTreeStructure() + + if(relativePath == "" || + relativePath == "." || + relativePath == "./") + { + subcollection <- private$tree$getTree() + } + else + { + relativePath <- trimFromEnd(relativePath, "/") subcollection <- self$get(relativePath) } if(is.null(subcollection)) stop(paste("Subcollection", relativePath, "doesn't exist.")) - if(is.character(content)) + if(is.character(fileNames)) { - sapply(content, function(fileName) + arvadosFiles <- NULL + sapply(fileNames, function(fileName) { - subcollection$add(ArvadosFile$new(fileName)) + childWithSameName <- subcollection$get(fileName) + if(!is.null(childWithSameName)) + stop("Destination already contains file with same name.") + + newFile <- ArvadosFile$new(fileName) + subcollection$add(newFile) + + arvadosFiles <<- c(arvadosFiles, newFile) }) + + if(length(arvadosFiles) == 1) + return(arvadosFiles[[1]]) + else + return(arvadosFiles) } - else if("ArvadosFile" %in% class(content) || - "Subcollection" %in% class(content)) + else { - subcollection$add(content) + stop(paste0("Expected character vector, got ", + paste0("(", paste0(class(fileNames), collapse = ", "), ")"), + ".")) } }, - remove = function(content) + remove = function(paths) { - if(is.character(content)) + if(is.null(private$tree)) + private$genereateCollectionTreeStructure() + + if(is.character(paths)) { - sapply(content, function(filePath) + sapply(paths, function(filePath) { - if(endsWith(filePath, "/") && nchar(filePath) > 0) - filePath <- substr(filePath, 1, nchar(filePath) - 1) - + filePath <- trimFromEnd(filePath, "/") file <- self$get(filePath) if(is.null(file)) stop(paste("File", filePath, "doesn't exist.")) - file$removeFromCollection() + parent <- file$getParent() + + if(is.null(parent)) + stop("You can't delete root folder.") + + parent$remove(file$getName()) }) + + "Content removed" } - else if("ArvadosFile" %in% class(content) || - "Subcollection" %in% class(content)) + else { - if(is.null(content$.__enclos_env__$private$collection) || - content$.__enclos_env__$private$collection$uuid != self$uuid) - stop("Subcollection doesn't belong to this collection.") - - content$removeFromCollection() + stop(paste0("Expected character vector, got ", + paste0("(", paste0(class(paths), collapse = ", "), ")"), + ".")) } }, move = function(content, newLocation) { - if(endsWith(content, "/")) - content <- substr(content, 0, nchar(content) - 1) + if(is.null(private$tree)) + private$genereateCollectionTreeStructure() + + content <- trimFromEnd(content, "/") elementToMove <- self$get(content) if(is.null(elementToMove)) - stop("Element you want to move doesn't exist in the collection.") + stop("Content you want to move doesn't exist in the collection.") elementToMove$move(newLocation) }, - getFileContent = function() private$getCollectionContent(), - - get = function(relativePath) + getFileListing = function() { - private$tree$getElement(relativePath) - } - ), - - private = list( - - http = NULL, - httpParser = NULL, - tree = NULL, + if(is.null(private$tree)) + private$genereateCollectionTreeStructure() - fileContent = NULL, - - getCollectionContent = function() - { - collectionURL <- URLencode(paste0(self$api$getWebDavHostName(), "c=", self$uuid)) - - headers = list("Authorization" = paste("OAuth2", self$api$getToken())) - - response <- private$http$PROPFIND(collectionURL, headers) - - parsedResponse <- private$httpParser$parseWebDAVResponse(response, collectionURL) - parsedResponse[-1] + content <- private$REST$getCollectionContent(self$uuid) + content[order(tolower(content))] }, - createFilesOnREST = function(files) - { - sapply(files, function(filePath) - { - private$createNewFile(filePath, NULL, "text/html") - }) - }, - - generateTree = function(content) + get = function(relativePath) { - treeBranches <- sapply(collectionContent, function(filePath) - { - splitPath <- unlist(strsplit(filePath$name, "/", fixed = TRUE)) + if(is.null(private$tree)) + private$genereateCollectionTreeStructure() - branch = private$createBranch(splitPath, filePath$fileSize) - }) + private$tree$getElement(relativePath) }, - createNewFile = function(relativePath, content, contentType) - { - fileURL <- paste0(self$api$getWebDavHostName(), "c=", self$uuid, "/", relativePath); - headers <- list(Authorization = paste("OAuth2", self$api$getToken()), - "Content-Type" = contentType) - body <- content - - serverResponse <- private$http$PUT(fileURL, headers, body) - - if(serverResponse$status_code < 200 || serverResponse$status_code >= 300) - stop(paste("Server code:", serverResponse$status_code)) - - print(paste("File created:", relativePath)) - }, - - deleteFromREST = function(relativePath) + toJSON = function() { - fileURL <- paste0(self$api$getWebDavHostName(), "c=", self$uuid, "/", relativePath); - headers <- list(Authorization = paste("OAuth2", self$api$getToken())) - - serverResponse <- private$http$DELETE(fileURL, headers) + fields <- sapply(private$classFields, function(field) + { + self[[field]] + }, USE.NAMES = TRUE) + + jsonlite::toJSON(list("collection" = + Filter(Negate(is.null), fields)), auto_unbox = TRUE) + }, + + isEmpty = function() { + fields <- sapply(private$classFields, + function(field) self[[field]]) + + if(any(sapply(fields, function(field) !is.null(field) && field != ""))) + FALSE + else + TRUE + }, + + getRESTService = function() private$REST, + setRESTService = function(newRESTService) private$REST <- newRESTService + ), - if(serverResponse$status_code < 200 || serverResponse$status_code >= 300) - stop(paste("Server code:", serverResponse$status_code)) + private = list( - print(paste("File deleted:", relativePath)) - }, + REST = NULL, + tree = NULL, + fileContent = NULL, + classFields = NULL, - moveOnREST = function(from, to) + genereateCollectionTreeStructure = function() { - collectionURL <- URLencode(paste0(self$api$getWebDavHostName(), "c=", self$uuid, "/")) - fromURL <- paste0(collectionURL, from) - toURL <- paste0(collectionURL, to) - - headers = list("Authorization" = paste("OAuth2", self$api$getToken()), - "Destination" = toURL) - - serverResponse <- private$http$MOVE(fromURL, headers) + if(is.null(self$uuid)) + stop("Collection uuid is not defined.") - if(serverResponse$status_code < 200 || serverResponse$status_code >= 300) - stop(paste("Server code:", serverResponse$status_code)) + if(is.null(private$REST)) + stop("REST service is not defined.") - serverResponse + private$fileContent <- private$REST$getCollectionContent(self$uuid) + private$tree <- CollectionTree$new(private$fileContent, self) } ), cloneable = FALSE ) + +#' print.Collection +#' +#' Custom print function for Collection class +#' +#' @param x Instance of Collection class +#' @param ... Optional arguments. +#' @export +print.Collection = function(x, ...) +{ + cat(paste0("Type: ", "\"", "Arvados Collection", "\""), sep = "\n") + cat(paste0("uuid: ", "\"", x$uuid, "\""), sep = "\n") +}