Improve Collections create and move methods and update documentation
[arvados.git] / sdk / R / R / Collection.R
index ba66c8b4b285992681b2fc21717226b9850f9144..8869d7be67846b449200fe2c675936dd1c4133db 100644 (file)
@@ -1,12 +1,16 @@
+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: Apache-2.0
+
 source("./R/Subcollection.R")
 source("./R/ArvadosFile.R")
 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)}
 #'
@@ -15,13 +19,14 @@ source("./R/util.R")
 #'   \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{create(files)}{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{move(content, destination)}{Moves ArvadosFile or Subcollection to another location in the collection.}
+#'   \item{copy(content, destination)}{Copies 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.}
 #' }
@@ -32,9 +37,6 @@ source("./R/util.R")
 #' 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/")
 #'
 #' collection$remove("location/to/my/file.cpp")
@@ -53,73 +55,18 @@ Collection <- R6::R6Class(
 
     public = list(
 
-               uuid                     = NULL,
-               etag                     = NULL,
-               owner_uuid               = NULL,
-               created_at               = NULL,
-               modified_by_client_uuid  = NULL,
-               modified_by_user_uuid    = NULL,
-               modified_at              = NULL,
-               portable_data_hash       = NULL,
-               replication_desired      = NULL,
-               replication_confirmed_at = NULL,
-               replication_confirmed    = NULL,
-               updated_at               = NULL,
-               manifest_text            = NULL,
-               name                     = NULL,
-               description              = NULL,
-               properties               = NULL,
-               delete_at                = NULL,
-               file_names               = NULL,
-               trash_at                 = NULL,
-               is_trashed               = NULL,
-
-               initialize = function(uuid = NULL, etag = NULL, owner_uuid = NULL,
-                              created_at = NULL, modified_by_client_uuid = NULL,
-                              modified_by_user_uuid = NULL, modified_at = NULL,
-                              portable_data_hash = NULL, replication_desired = NULL,
-                              replication_confirmed_at = NULL,
-                              replication_confirmed = NULL, updated_at = NULL,
-                              manifest_text = NULL, name = NULL, description = NULL,
-                              properties = NULL, delete_at = NULL, file_names = NULL,
-                              trash_at = NULL, is_trashed = NULL) 
+               uuid = NULL,
+
+               initialize = function(api, uuid)
         {
-                       self$uuid                     <- uuid
-                       self$etag                     <- etag
-                       self$owner_uuid               <- owner_uuid
-                       self$created_at               <- created_at
-                       self$modified_by_client_uuid  <- modified_by_client_uuid
-                       self$modified_by_user_uuid    <- modified_by_user_uuid
-                       self$modified_at              <- modified_at
-                       self$portable_data_hash       <- portable_data_hash
-                       self$replication_desired      <- replication_desired
-                       self$replication_confirmed_at <- replication_confirmed_at
-                       self$replication_confirmed    <- replication_confirmed
-                       self$updated_at               <- updated_at
-                       self$manifest_text            <- manifest_text
-                       self$name                     <- name
-                       self$description              <- description
-                       self$properties               <- properties
-                       self$delete_at                <- delete_at
-                       self$file_names               <- file_names
-                       self$trash_at                 <- trash_at
-                       self$is_trashed               <- is_trashed
-                       
-                       private$classFields <- c("uuid", "etag", "owner_uuid", 
-                                     "created_at", "modified_by_client_uuid",
-                                     "modified_by_user_uuid", "modified_at",
-                                     "portable_data_hash", "replication_desired",
-                                     "replication_confirmed_at",
-                                     "replication_confirmed", "updated_at",
-                                     "manifest_text", "name", "description", 
-                                     "properties", "delete_at", "file_names",
-                                     "trash_at", "is_trashed")
+            private$REST <- api$getRESTService()
+            self$uuid <- uuid
         },
 
         add = function(content, relativePath = "")
         {
             if(is.null(private$tree))
-                private$genereateCollectionTreeStructure()
+                private$generateCollectionTreeStructure()
 
             if(relativePath == ""  ||
                relativePath == "." ||
@@ -139,6 +86,9 @@ Collection <- R6::R6Class(
             if("ArvadosFile"   %in% class(content) ||
                "Subcollection" %in% class(content))
             {
+                if(!is.null(content$getCollection()))
+                    stop("Content already belongs to a collection.")
+
                 if(content$getName() == "")
                     stop("Content has invalid name.")
 
@@ -153,50 +103,32 @@ Collection <- R6::R6Class(
             }
         },
 
-        create = function(fileNames, relativePath = "")
+        create = function(files)
         {
             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."))
+                private$generateCollectionTreeStructure()
 
-            if(is.character(fileNames))
+            if(is.character(files))
             {
-                arvadosFiles <- NULL
-                sapply(fileNames, function(fileName)
+                sapply(files, function(file)
                 {
-                    childWithSameName <- subcollection$get(fileName)
+                    childWithSameName <- self$get(file)
                     if(!is.null(childWithSameName))
                         stop("Destination already contains file with same name.")
 
-                    newFile <- ArvadosFile$new(fileName)
-                    subcollection$add(newFile)
+                    newTreeBranch <- private$tree$createBranch(file)
+                    private$tree$addBranch(private$tree$getTree(), newTreeBranch)
 
-                    arvadosFiles <<- c(arvadosFiles, newFile)
+                    private$REST$create(file, self$uuid)
+                    newTreeBranch$setCollection(self)
                 })
 
-                if(length(arvadosFiles) == 1)
-                    return(arvadosFiles[[1]])
-                else
-                    return(arvadosFiles)
+                "Created"
             }
-            else 
+            else
             {
                 stop(paste0("Expected character vector, got ",
-                            paste0("(", paste0(class(fileNames), collapse = ", "), ")"),
+                            paste0("(", paste0(class(files), collapse = ", "), ")"),
                             "."))
             }
         },
@@ -204,7 +136,7 @@ Collection <- R6::R6Class(
         remove = function(paths)
         {
             if(is.null(private$tree))
-                private$genereateCollectionTreeStructure()
+                private$generateCollectionTreeStructure()
 
             if(is.character(paths))
             {
@@ -226,7 +158,7 @@ Collection <- R6::R6Class(
 
                 "Content removed"
             }
-            else 
+            else
             {
                 stop(paste0("Expected character vector, got ",
                             paste0("(", paste0(class(paths), collapse = ", "), ")"),
@@ -234,10 +166,10 @@ Collection <- R6::R6Class(
             }
         },
 
-        move = function(content, newLocation)
+        move = function(content, destination)
         {
             if(is.null(private$tree))
-                private$genereateCollectionTreeStructure()
+                private$generateCollectionTreeStructure()
 
             content <- trimFromEnd(content, "/")
 
@@ -246,13 +178,37 @@ Collection <- R6::R6Class(
             if(is.null(elementToMove))
                 stop("Content you want to move doesn't exist in the collection.")
 
-            elementToMove$move(newLocation)
+            elementToMove$move(destination)
+        },
+
+        copy = function(content, destination)
+        {
+            if(is.null(private$tree))
+                private$generateCollectionTreeStructure()
+
+            content <- trimFromEnd(content, "/")
+
+            elementToCopy <- self$get(content)
+
+            if(is.null(elementToCopy))
+                stop("Content you want to copy doesn't exist in the collection.")
+
+            elementToCopy$copy(destination)
+        },
+
+        refresh = function()
+        {
+            if(!is.null(private$tree))
+            {
+                private$tree$getTree()$setCollection(NULL, setRecursively = TRUE)
+                private$tree <- NULL
+            }
         },
 
         getFileListing = function()
         {
             if(is.null(private$tree))
-                private$genereateCollectionTreeStructure()
+                private$generateCollectionTreeStructure()
 
             content <- private$REST$getCollectionContent(self$uuid)
             content[order(tolower(content))]
@@ -261,22 +217,11 @@ Collection <- R6::R6Class(
         get = function(relativePath)
         {
             if(is.null(private$tree))
-                private$genereateCollectionTreeStructure()
+                private$generateCollectionTreeStructure()
 
             private$tree$getElement(relativePath)
         },
 
-               toJSON = function() 
-        {
-                       fields <- sapply(private$classFields, function(field)
-                       {
-                               self[[field]]
-                       }, USE.NAMES = TRUE)
-                       
-                       jsonlite::toJSON(list("collection" = 
-                     Filter(Negate(is.null), fields)), auto_unbox = TRUE)
-               },
-
         getRESTService = function() private$REST,
         setRESTService = function(newRESTService) private$REST <- newRESTService
     ),
@@ -286,9 +231,8 @@ Collection <- R6::R6Class(
         REST        = NULL,
         tree        = NULL,
         fileContent = NULL,
-        classFields = NULL,
 
-        genereateCollectionTreeStructure = function()
+        generateCollectionTreeStructure = function()
         {
             if(is.null(self$uuid))
                 stop("Collection uuid is not defined.")
@@ -310,7 +254,7 @@ Collection <- R6::R6Class(
 #'
 #' @param x Instance of Collection class
 #' @param ... Optional arguments.
-#' @export 
+#' @export
 print.Collection = function(x, ...)
 {
     cat(paste0("Type: ", "\"", "Arvados Collection", "\""), sep = "\n")