[ARVADOS] updated: 1.1.1-295-gf15c8a8

Git user git at public.curoverse.com
Mon Dec 18 10:39:53 EST 2017


Summary of changes:
 build/run-build-packages-all-targets.sh            |   4 +-
 build/run-build-packages-one-target.sh             |   4 +-
 build/run-build-test-packages-one-target.sh        |  18 +-
 sdk/ArvadosSDK_0.1.0_R_x86_64-pc-linux-gnu.tar.gz  | Bin 40806 -> 0 bytes
 sdk/R/.RData                                       | Bin 192106 -> 189909 bytes
 sdk/R/NAMESPACE                                    |   2 +
 sdk/R/R/ArvadosFile.R                              |  99 +++++---
 sdk/R/R/CTest.R                                    | 173 ++++++++++++++
 sdk/R/R/Collection.R                               | 260 ++++++++-------------
 sdk/R/R/CollectionTree.R                           | 112 +++++++++
 sdk/R/R/FileTree.R                                 | 202 ----------------
 sdk/R/R/HttpParser.R                               |  28 ++-
 sdk/R/R/Subcollection.R                            | 166 +++++++++++--
 sdk/R/README                                       |  44 +++-
 sdk/R/man/{Collection.Rd => CTest.Rd}              |   6 +-
 sdk/R/man/Collection.Rd                            |   2 +-
 sdk/R/man/{Collection.Rd => CollectionTree.Rd}     |   8 +-
 tools/arvbox/lib/arvbox/docker/common.sh           |   1 +
 .../lib/arvbox/docker/service/composer/run-service |   2 +-
 .../arvbox/docker/service/workbench/run-service    |   1 +
 20 files changed, 694 insertions(+), 438 deletions(-)
 delete mode 100644 sdk/ArvadosSDK_0.1.0_R_x86_64-pc-linux-gnu.tar.gz
 create mode 100644 sdk/R/R/CTest.R
 create mode 100644 sdk/R/R/CollectionTree.R
 delete mode 100644 sdk/R/R/FileTree.R
 copy sdk/R/man/{Collection.Rd => CTest.Rd} (86%)
 copy sdk/R/man/{Collection.Rd => CollectionTree.Rd} (70%)

       via  f15c8a8ef1af9d823030f4c6383ba2560a78a4fa (commit)
       via  df8b4a86d08b4da0f5959766257664c9af89343b (commit)
       via  398d468a26349ff3ef4819facb268912a72e2896 (commit)
       via  6cf3825010724a7d2ebceac5666c89090fadcb91 (commit)
       via  71a83590c5d6804a98d8fa3203acba69820814d8 (commit)
      from  7da8eaf51a23ab23369b6e65f0634448cc4aeb3b (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit f15c8a8ef1af9d823030f4c6383ba2560a78a4fa
Merge: df8b4a8 398d468
Author: Fuad Muhic <fmuhic at capeannenterprises.com>
Date:   Mon Dec 18 16:39:41 2017 +0100

    Merge branch 'master' of git.curoverse.com:arvados into 11876-r-sdk
    
    Arvados-DCO-1.1-Signed-off-by: Fuad Muhic <fmuhic at capeannenterprises.com>


commit df8b4a86d08b4da0f5959766257664c9af89343b
Author: Fuad Muhic <fmuhic at capeannenterprises.com>
Date:   Mon Dec 18 16:37:44 2017 +0100

    Made Subcollection and ArvadosFile more flexible.
    
    Arvados-DCO-1.1-Signed-off-by: Fuad Muhic <fmuhic at capeannenterprises.com>

diff --git a/sdk/ArvadosSDK_0.1.0_R_x86_64-pc-linux-gnu.tar.gz b/sdk/ArvadosSDK_0.1.0_R_x86_64-pc-linux-gnu.tar.gz
deleted file mode 100644
index aa802dd..0000000
Binary files a/sdk/ArvadosSDK_0.1.0_R_x86_64-pc-linux-gnu.tar.gz and /dev/null differ
diff --git a/sdk/R/.RData b/sdk/R/.RData
index 19eceda..1344e2a 100644
Binary files a/sdk/R/.RData and b/sdk/R/.RData differ
diff --git a/sdk/R/NAMESPACE b/sdk/R/NAMESPACE
index 411deb8..8b2f567 100644
--- a/sdk/R/NAMESPACE
+++ b/sdk/R/NAMESPACE
@@ -2,5 +2,7 @@
 
 export(Arvados)
 export(ArvadosFile)
+export(CTest)
 export(Collection)
+export(CollectionTree)
 export(Subcollection)
diff --git a/sdk/R/R/ArvadosFile.R b/sdk/R/R/ArvadosFile.R
index 563eaa2..c8950c6 100644
--- a/sdk/R/R/ArvadosFile.R
+++ b/sdk/R/R/ArvadosFile.R
@@ -9,25 +9,66 @@ ArvadosFile <- R6::R6Class(
 
     public = list(
 
-        initialize = function(name, relativePath, size, api, collection)
+        initialize = function(name)
         {
-            private$name         <- name
-            private$size         <- size
-            private$relativePath <- relativePath
-            private$api          <- api
-            private$collection   <- collection
-            private$http         <- HttpRequest$new()
-            private$httpParser   <- HttpParser$new()
+            private$name       <- name
+            private$http       <- HttpRequest$new()
+            private$httpParser <- HttpParser$new()
         },
 
         getName = function() private$name,
 
-        getRelativePath = function() private$relativePath,
+        getFileList = function(fullpath = TRUE)
+        {
+            self$getName()
+        },
+
+        getSizeInBytes = function()
+        {
+            collectionURL <- URLencode(paste0(private$collection$api$getWebDavHostName(), "c=", private$collection$uuid))
+            fileURL <- paste0(collectionURL, "/", self$getRelativePath());
+
+            headers = list("Authorization" = paste("OAuth2", private$collection$api$getToken()))
+
+            propfindResponse <- private$http$PROPFIND(fileURL, headers)
 
-        getSizeInBytes = function() private$size,
+            sizes <- private$httpParser$extractFileSizeFromWebDAVResponse(propfindResponse, collectionURL)
+            as.numeric(sizes)
+        },
+
+        removeFromCollection = function()
+        {
+            if(is.null(private$collection))
+                stop("Subcollection doesn't belong to any collection.")
+            
+            private$collection$.__enclos_env__$private$deleteFromREST(self$getRelativePath())
+
+            #todo rename this add to a collection
+            private$addToCollection(NULL)
+            private$detachFromParent()
+        },
+
+        getRelativePath = function()
+        {
+            relativePath <- c(private$name)
+            parent <- private$parent
+
+            #Recurse back to root
+            while(!is.null(parent))
+            {
+                relativePath <- c(parent$getName(), relativePath)
+                parent <- parent$getParent()
+            }
+
+            relativePath <- relativePath[relativePath != ""]
+            paste0(relativePath, collapse = "/")
+        },
+
+        getParent = function() private$parent,
 
         read = function(offset = 0, length = 0)
         {
+            #todo range is wrong fix it
             if(offset < 0 || length < 0)
             stop("Offset and length must be positive values.")
 
@@ -36,8 +77,8 @@ ArvadosFile <- R6::R6Class(
             if(length > 0)
                 range = paste0(range, offset + length - 1)
             
-            fileURL = paste0(private$api$getWebDavHostName(), "c=", private$collection$uuid, "/", private$relativePath);
-            headers <- list(Authorization = paste("OAuth2", private$api$getToken()), 
+            fileURL = paste0(private$collection$api$getWebDavHostName(), "c=", private$collection$uuid, "/", self$getRelativePath());
+            headers <- list(Authorization = paste("OAuth2", private$collection$api$getToken()), 
                             Range = range)
 
             serverResponse <- private$http$GET(fileURL, headers)
@@ -51,8 +92,8 @@ ArvadosFile <- R6::R6Class(
         
         write = function(content, contentType = "text/html")
         {
-            fileURL = paste0(private$api$getWebDavHostName(), "c=", private$collection$uuid, "/", private$relativePath);
-            headers <- list(Authorization = paste("OAuth2", private$api$getToken()), 
+            fileURL = paste0(private$collection$api$getWebDavHostName(), "c=", private$collection$uuid, "/", self$getRelativePath());
+            headers <- list(Authorization = paste("OAuth2", private$collection$api$getToken()), 
                             "Content-Type" = contentType)
             body <- content
 
@@ -61,8 +102,6 @@ ArvadosFile <- R6::R6Class(
             if(serverResponse$status_code != 201)
                 stop(paste("Server code:", serverResponse$status_code))
 
-            private$notifyCollectionThatFileSizeChanges()
-
             parsedServerResponse <- httr::content(serverResponse, "text")
             parsedServerResponse
         }
@@ -71,26 +110,34 @@ ArvadosFile <- R6::R6Class(
     private = list(
 
         name         = NULL,
-        relativePath = NULL,
         size         = NULL,
         parent       = NULL,
-        api          = NULL,
         collection   = NULL,
         http         = NULL,
         httpParser   = NULL,
 
-        notifyCollectionThatFileSizeChanges = function()
+        getChild = function(name)
         {
-            collectionURL <- URLencode(paste0(private$api$getWebDavHostName(), "c=", private$collection$uuid))
-            fileURL = paste0(collectionURL, "/", private$relativePath);
-            headers = list("Authorization" = paste("OAuth2", private$api$getToken()))
+            return(NULL)
+        },
 
-            propfindResponse <- private$http$PROPFIND(fileURL, headers)
+        getFirstChild = function()
+        {
+            return(NULL)
+        },
 
-            fileInfo <- private$httpParser$parseWebDAVResponse(propfindResponse, collectionURL)
+        addToCollection = function(collection)
+        {
+            private$collection = collection
+        },
 
-            private$size <- fileInfo[[1]]$fileSize
-            private$collection$update(self, "File size changed")
+        detachFromParent = function()
+        {
+            if(!is.null(private$parent))
+            {
+                private$parent$.__enclos_env__$private$removeChild(private$name)
+                private$parent <- NULL
+            }
         }
     ),
     
diff --git a/sdk/R/R/CTest.R b/sdk/R/R/CTest.R
new file mode 100644
index 0000000..bdef950
--- /dev/null
+++ b/sdk/R/R/CTest.R
@@ -0,0 +1,173 @@
+source("./R/Subcollection.R")
+source("./R/ArvadosFile.R")
+source("./R/HttpRequest.R")
+source("./R/HttpParser.R")
+
+#' Arvados Collection Object
+#'
+#' Update description
+#'
+#' @examples arv = Collection$new(api, uuid)
+#' @export Collection
+Collection <- R6::R6Class(
+
+    "Collection",
+
+    public = list(
+
+        api  = NULL,
+        uuid = NULL,
+
+        initialize = function(api, uuid)
+        {
+            self$api <- api
+            private$http <- HttpRequest$new()
+            private$httpParser <- HttpParser$new()
+
+            self$uuid <- uuid
+            collection <- self$api$getCollection(uuid)
+
+            private$fileContent <- private$getCollectionContent()
+            private$tree <- CollectionTree$new(private$fileContent, self)
+        },
+
+        add = function(content, relativePath = "")
+        {
+            if(relativePath == "" ||
+               relativePath == "." ||
+               relativePath == "./")
+            {
+                subcollection <- private$tree$.__enclos_env__$private$tree
+            }
+            else
+            {
+                if(endsWith(relativePath, "/") && nchar(relativePath) > 0)
+                    relativePath <- substr(relativePath, 1, nchar(relativePath) - 1)
+
+                subcollection <- self$get(relativePath)
+            }
+
+            if(is.null(subcollection))
+                stop(paste("Subcollection", relativePath, "doesn't exist."))
+
+            if(is.character(content))
+            {
+                sapply(content, function(fileName)
+                {
+                    subcollection$add(ArvadosFile$new(fileName))
+                })
+            }
+            else if("ArvadosFile"   %in% class(content) ||
+                    "Subcollection" %in% class(content))
+            {
+                subcollection$add(content)
+            }
+        },
+
+        remove = function(content)
+        {
+            if(is.character(content))
+            {
+                sapply(content, function(filePath)
+                {
+                    if(endsWith(filePath, "/") && nchar(filePath) > 0)
+                        filePath <- substr(filePath, 1, nchar(filePath) - 1)
+
+                    file <- self$get(filePath)
+
+                    if(is.null(file))
+                        stop(paste("File", filePath, "doesn't exist."))
+
+                    file$removeFromCollection()
+                })
+            }
+            else if("ArvadosFile"   %in% class(content) ||
+                    "Subcollection" %in% class(content))
+            {
+                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()
+            }
+        },
+
+        getTree = function() private$tree,
+
+        getFileContent = function() private$getCollectionContent(),
+
+        get = function(relativePath)
+        {
+            private$tree$getElement(relativePath)
+        }
+    ),
+
+    private = list(
+
+        http       = NULL,
+        httpParser = NULL,
+        tree       = NULL,
+
+        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]
+        },
+
+        createFilesOnREST = function(files)
+        {
+            sapply(files, function(filePath)
+            {
+                private$createNewFile(filePath, NULL, "text/html")
+            })
+        },
+        
+        generateTree = function(content)
+        {
+            treeBranches <- sapply(collectionContent, function(filePath)
+            {
+                splitPath <- unlist(strsplit(filePath$name, "/", fixed = TRUE))
+
+                branch = private$createBranch(splitPath, filePath$fileSize)      
+            })
+        },
+
+        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 != 201)
+                stop(paste("Server code:", serverResponse$status_code))
+
+            print(paste("File created:", relativePath))
+        },
+        
+        deleteFromREST = function(relativePath)
+        {
+            fileURL <- paste0(self$api$getWebDavHostName(), "c=", self$uuid, "/", relativePath);
+            headers <- list(Authorization = paste("OAuth2", self$api$getToken())) 
+
+            serverResponse <- private$http$DELETE(fileURL, headers)
+
+            if(serverResponse$status_code != 204)
+                stop(paste("Server code:", serverResponse$status_code))
+
+            print(paste("File deleted", relativePath))
+        }
+    ),
+
+    cloneable = FALSE
+)
diff --git a/sdk/R/R/Collection.R b/sdk/R/R/Collection.R
index 49a1e81..94141d9 100644
--- a/sdk/R/R/Collection.R
+++ b/sdk/R/R/Collection.R
@@ -1,6 +1,5 @@
 source("./R/Subcollection.R")
 source("./R/ArvadosFile.R")
-source("./R/FileTree.R")
 source("./R/HttpRequest.R")
 source("./R/HttpParser.R")
 
@@ -9,225 +8,162 @@ source("./R/HttpParser.R")
 #' Update description
 #'
 #' @examples arv = Collection$new(api, uuid)
-#' @export Collection
-Collection <- R6::R6Class(
-
-    "Collection",
-
+#' @export CTest
+CTest <- R6::R6Class(
+    "CTest",
     public = list(
 
-        #Todo(Fudo): Encapsulate this?
-        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,
+        api  = NULL,
+        uuid = NULL,
 
         initialize = function(api, uuid)
         {
-            private$api <- api
-            result <- private$api$getCollection(uuid)
-
-            self$uuid                     <- result$uuid                               
-            self$etag                     <- result$etag                               
-            self$owner_uuid               <- result$owner_uuid                         
-            self$created_at               <- result$created_at                         
-            self$modified_by_client_uuid  <- result$modified_by_client_uuid            
-            self$modified_by_user_uuid    <- result$modified_by_user_uuid              
-            self$modified_at              <- result$modified_at                        
-            self$portable_data_hash       <- result$portable_data_hash                 
-            self$replication_desired      <- result$replication_desired                
-            self$replication_confirmed_at <- result$replication_confirmed_at           
-            self$replication_confirmed    <- result$replication_confirmed              
-            self$updated_at               <- result$updated_at                         
-            self$manifest_text            <- result$manifest_text                      
-            self$name                     <- result$name                               
-            self$description              <- result$description                        
-            self$properties               <- result$properties                         
-            self$delete_at                <- result$delete_at                          
-            self$file_names               <- result$file_names                         
-            self$trash_at                 <- result$trash_at                           
-            self$is_trashed               <- result$is_trashed                         
-
+            self$api <- api
             private$http <- HttpRequest$new()
             private$httpParser <- HttpParser$new()
 
-            private$fileItems <- private$getCollectionContent()
-            private$fileTree <- FileTree$new(private$fileItems)
-
-        },
+            self$uuid <- uuid
+            collection <- self$api$getCollection(uuid)
 
-        printFileContent = function()
-        {
-            private$fileTree$printContent(private$fileTree$getRoot(), 0)
+            private$fileContent <- private$getCollectionContent()
+            private$tree <- CollectionTree$new(private$fileContent, self)
         },
 
-        getFileContent = function()
+        add = function(content, relativePath = "")
         {
-            sapply(private$fileItems, function(file)
+            if(relativePath == "" ||
+               relativePath == "." ||
+               relativePath == "./")
             {
-                file$name
-            })
-        },
-
-        get = function(relativePath)
-        {
-            treeNode <- private$fileTree$traverseInOrder(private$fileTree$getRoot(), function(node)
+                subcollection <- private$tree$.__enclos_env__$private$tree
+            }
+            else
             {
-                if(node$relativePath == relativePath)
-                    return(node)
-                else
-                    return(NULL)
-            })
+                if(endsWith(relativePath, "/") && nchar(relativePath) > 0)
+                    relativePath <- substr(relativePath, 1, nchar(relativePath) - 1)
+
+                subcollection <- self$get(relativePath)
+            }
+
+            if(is.null(subcollection))
+                stop(paste("Subcollection", relativePath, "doesn't exist."))
 
-            if(!is.null(treeNode))
+            if(is.character(content))
             {
-                return(private$createSubcollectionTree(treeNode))
+                sapply(content, function(fileName)
+                {
+                    subcollection$add(ArvadosFile$new(fileName))
+                })
             }
-            else
+            else if("ArvadosFile"   %in% class(content) ||
+                    "Subcollection" %in% class(content))
             {
-                return(NULL)
+                subcollection$add(content)
             }
         },
 
-        createNewFile = function(relativePath, content, contentType)
+        remove = function(content)
         {
-            fileURL <- paste0(private$api$getWebDavHostName(), "c=", self$uuid, "/", relativePath);
-            headers <- list(Authorization = paste("OAuth2", private$api$getToken()), 
-                            "Content-Type" = contentType)
-            body <- content
+            if(is.character(content))
+            {
+                sapply(content, function(filePath)
+                {
+                    if(endsWith(filePath, "/") && nchar(filePath) > 0)
+                        filePath <- substr(filePath, 1, nchar(filePath) - 1)
 
-            serverResponse <- private$http$PUT(fileURL, headers, body)
+                    file <- self$get(filePath)
 
-            if(serverResponse$status_code != 201)
-                stop(paste("Server code:", serverResponse$status_code))
+                    if(is.null(file))
+                        stop(paste("File", filePath, "doesn't exist."))
 
-            fileSize = private$getNewFileSize(relativePath)
-            private$fileTree$addNode(relativePath, fileSize)
+                    file$removeFromCollection()
+                })
+            }
+            else if("ArvadosFile"   %in% class(content) ||
+                    "Subcollection" %in% class(content))
+            {
+                if(is.null(content$.__enclos_env__$private$collection) || 
+                   content$.__enclos_env__$private$collection$uuid != self$uuid)
+                    stop("Subcollection doesn't belong to this collection.")
 
-            paste0("File created (size = ", fileSize , ")")
+                content$removeFromCollection()
+            }
         },
 
-        removeFile = function(relativePath)
-        {
-            node <- private$fileTree$getNode(relativePath)
-
-            if(is.null(node))
-                stop("File doesn't exists.")
-
-            fileURL <- paste0(private$api$getWebDavHostName(), "c=", self$uuid, "/", relativePath);
-            headers <- list(Authorization = paste("OAuth2", private$api$getToken())) 
-
-            serverResponse <- private$http$DELETE(fileURL, headers)
+        getTree = function() private$tree,
 
-            if(serverResponse$status_code != 204)
-                stop(paste("Server code:", serverResponse$status_code))
-
-            "File deleted"
-        },
+        getFileContent = function() private$getCollectionContent(),
 
-        update = function(subcollection, event)
+        get = function(relativePath)
         {
-            #Todo(Fudo): Add some king of check here later on.
-            if(event == "File size changed")
-            {
-                private$handleFileSizeChange(subcollection$getRelativePath(),
-                                             subcollection$getSizeInBytes())
-            }
+            private$tree$getElement(relativePath)
         }
     ),
 
-    active = list(
-        items = function(value)
-        {
-            if(missing(value))
-                return(private$fileItems)
-            else
-                print("Value is read-only.")
-
-            return(NULL)
-        }
-    ),
-    
     private = list(
 
-        fileItems  = NULL,
-        api        = NULL,
-        fileTree   = NULL,
         http       = NULL,
         httpParser = NULL,
+        tree       = NULL,
 
-        handleFileSizeChange = function(filePath, newSize)
+        fileContent = NULL,
+
+        getCollectionContent = function()
         {
-            node <- private$fileTree$getNode(filePath)
+            collectionURL <- URLencode(paste0(self$api$getWebDavHostName(), "c=", self$uuid))
 
-            if(is.null(node))
-                stop("File doesn't exits")
+            headers = list("Authorization" = paste("OAuth2", self$api$getToken()))
 
-            node$size <- newSize
+            response <- private$http$PROPFIND(collectionURL, headers)
+
+            parsedResponse <- private$httpParser$parseWebDAVResponse(response, collectionURL)
+            parsedResponse[-1]
         },
 
-        createSubcollectionTree = function(treeNode)
+        createFilesOnREST = function(files)
         {
-            if(treeNode$hasChildren())
+            sapply(files, function(filePath)
             {
-                children = NULL
-
-                for(child in treeNode$children)
-                {
-                    child <- private$createSubcollectionTree(child)
-                    children <- c(children, child)                   
-                }
-
-                return(Subcollection$new(treeNode$name, treeNode$relativePath, children))
-            }
-            else
+                private$createNewFile(filePath, NULL, "text/html")
+            })
+        },
+        
+        generateTree = function(content)
+        {
+            treeBranches <- sapply(collectionContent, function(filePath)
             {
-                if(treeNode$type == "file")
-                    return(ArvadosFile$new(treeNode$name, treeNode$relativePath, treeNode$size, private$api, self))
-                else 
-                    return(Subcollection$new(treeNode$name, treeNode$relativePath, NULL))
-            }
+                splitPath <- unlist(strsplit(filePath$name, "/", fixed = TRUE))
+
+                branch = private$createBranch(splitPath, filePath$fileSize)      
+            })
         },
 
-        getCollectionContent = function()
+        createNewFile = function(relativePath, content, contentType)
         {
-            collectionURL <- URLencode(paste0(private$api$getWebDavHostName(), "c=", self$uuid))
+            fileURL <- paste0(self$api$getWebDavHostName(), "c=", self$uuid, "/", relativePath);
+            headers <- list(Authorization = paste("OAuth2", self$api$getToken()), 
+                            "Content-Type" = contentType)
+            body <- content
 
-            headers = list("Authorization" = paste("OAuth2", private$api$getToken()))
+            serverResponse <- private$http$PUT(fileURL, headers, body)
 
-            response <- private$http$PROPFIND(collectionURL, headers)
+            if(serverResponse$status_code != 201)
+                stop(paste("Server code:", serverResponse$status_code))
 
-            parsedResponse <- private$httpParser$parseWebDAVResponse(response, collectionURL)
-            parsedResponse[-1]
+            print(paste("File created:", relativePath))
         },
-
-        getNewFileSize = function(relativePath)
+        
+        deleteFromREST = function(relativePath)
         {
-            collectionURL <- URLencode(paste0(private$api$getWebDavHostName(), "c=", self$uuid))
-            fileURL = paste0(collectionURL, "/", relativePath);
-            headers = list("Authorization" = paste("OAuth2", private$api$getToken()))
+            fileURL <- paste0(self$api$getWebDavHostName(), "c=", self$uuid, "/", relativePath);
+            headers <- list(Authorization = paste("OAuth2", self$api$getToken())) 
 
-            propfindResponse <- private$http$PROPFIND(fileURL, headers)
+            serverResponse <- private$http$DELETE(fileURL, headers)
 
-            fileInfo <- private$httpParser$parseWebDAVResponse(propfindResponse, collectionURL)
+            if(serverResponse$status_code != 204)
+                stop(paste("Server code:", serverResponse$status_code))
 
-            fileInfo[[1]]$fileSize
+            print(paste("File deleted", relativePath))
         }
     ),
 
diff --git a/sdk/R/R/CollectionTree.R b/sdk/R/R/CollectionTree.R
new file mode 100644
index 0000000..cf8c6eb
--- /dev/null
+++ b/sdk/R/R/CollectionTree.R
@@ -0,0 +1,112 @@
+source("./R/Subcollection.R")
+source("./R/ArvadosFile.R")
+
+#' Arvados Collection Object
+#'
+#' Update description
+#'
+#' @examples arv = Collection$new(api, uuid)
+#' @export CollectionTree
+CollectionTree <- R6::R6Class(
+    "CollectionTree",
+    public = list(
+
+        pathsList = NULL,
+
+        initialize = function(fileContent, collection)
+        {
+            self$pathsList <- fileContent
+
+            treeBranches <- sapply(fileContent, function(filePath)
+            {
+                splitPath <- unlist(strsplit(filePath, "/", fixed = TRUE))
+                branch = private$createBranch(splitPath)      
+            })
+
+            root <- Subcollection$new("")
+
+            sapply(treeBranches, function(branch)
+            {
+                private$addBranch(root, branch)
+            })
+
+            root$.__enclos_env__$private$addToCollection(collection)
+            private$tree <- root
+        },
+
+        getElement = function(relativePath)
+        {
+            splitPath <- unlist(strsplit(relativePath, "/", fixed = TRUE))
+            returnElement = private$tree
+
+            for(pathFragment in splitPath)
+            {
+                returnElement = returnElement$.__enclos_env__$private$getChild(pathFragment)
+
+                if(is.null(returnElement))
+                    return(NULL)
+            }
+
+            returnElement
+        }
+    ),
+
+    private = list(
+
+        tree = NULL,
+
+        createBranch = function(splitPath)
+        {
+            branch <- NULL
+            lastElementIndex <- length(splitPath)
+
+            for(elementIndex in lastElementIndex:1)
+            {
+            if(elementIndex == lastElementIndex)
+                {
+                    branch = ArvadosFile$new(splitPath[[elementIndex]])
+                }
+                else
+                {
+                    newFolder = Subcollection$new(splitPath[[elementIndex]])
+                    newFolder$add(branch)
+                    branch = newFolder
+                }
+            }
+            
+            branch
+        },
+
+        addBranch = function(container, node)
+        {
+            child = container$.__enclos_env__$private$getChild(node$getName())
+
+            if(is.null(child))
+            {
+                container$add(node)
+                #todo add it to collection
+            }
+            else
+            {
+                if("ArvadosFile" %in% class(child))
+                {
+                    child = private$replaceFileWithSubcollection(child)
+                }
+
+                private$addBranch(child, node$.__enclos_env__$private$getFirstChild())
+            }
+        },
+
+        replaceFileWithSubcollection = function(arvadosFile)
+        {
+            subcollection <- Subcollection$new(arvadosFile$getName())
+            fileParent <- arvadosFile$.__enclos_env__$private$parent
+            fileParent$.__enclos_env__$private$removeChild(arvadosFile$getName())
+            fileParent$add(subcollection)
+
+            arvadosFile$.__enclos_env__$private$parent <- NULL
+
+            subcollection
+        }
+    )
+)
diff --git a/sdk/R/R/FileTree.R b/sdk/R/R/FileTree.R
deleted file mode 100644
index 4b21fda..0000000
--- a/sdk/R/R/FileTree.R
+++ /dev/null
@@ -1,202 +0,0 @@
-FileTree <- R6::R6Class(
-    "FileTree",
-    public = list(
-        initialize = function(collectionContent)
-        {
-            treeBranches <- sapply(collectionContent, function(filePath)
-            {
-                splitPath <- unlist(strsplit(filePath$name, "/", fixed = TRUE))
-
-                branch = private$createBranch(splitPath, filePath$fileSize)      
-            })
-
-            root <- TreeNode$new("./", "root", NULL)
-            root$relativePath = ""
-
-            sapply(treeBranches, function(branch)
-            {
-                private$addBranch(root, branch)
-            })
-
-            private$tree <- root
-        },
-
-        getRoot = function() private$tree,
-
-        printContent = function(node, depth)
-        {
-            indentation <- paste(rep("....", depth), collapse = "")
-            if(node$type == "folder")
-                print(paste0(indentation, node$name, "/"))
-            else
-                print(paste0(indentation, node$name))
-            
-            for(child in node$children)
-                self$printContent(child, depth + 1)
-        },
-
-        traverseInOrder = function(node, predicate)
-        {
-            if(node$hasChildren())
-            {
-                result <- predicate(node)
-
-                if(!is.null(result))
-                    return(result)               
-
-                for(child in node$children)
-                {
-                    result <- self$traverseInOrder(child, predicate)
-
-                    if(!is.null(result))
-                        return(result)
-                }
-
-                return(NULL)
-            }
-            else
-            {
-                return(predicate(node))
-            }
-        },
-
-        getNode = function(relativePathToNode)
-        {
-            treeBranches <- sapply(relativePathToNode, function(filePath)
-            {
-                splitPath <- unlist(strsplit(filePath, "/", fixed = TRUE))
-                
-                node <- private$tree
-                for(pathFragment in splitPath)
-                {
-                    child = node$getChild(pathFragment)
-
-                    if(is.null(child))
-                        return(NULL)
-
-                    node = child
-                }
-
-                node
-            })
-        },
-
-        addNode = function(relativePathToNode, size)
-        {
-            splitPath <- unlist(strsplit(relativePathToNode, "/", fixed = TRUE))
-
-            branch <- private$createBranch(splitPath, size)
-            private$addBranch(private$tree, branch)
-        }
-    ),
-
-    private = list(
-        tree = NULL,
-
-        createBranch = function(splitPath, fileSize)
-        {
-            branch <- NULL
-            lastElementIndex <- length(splitPath)
-
-            for(elementIndex in lastElementIndex:1)
-            {
-                if(elementIndex == lastElementIndex)
-                {
-                    branch = TreeNode$new(splitPath[[elementIndex]], "file", fileSize)
-                }
-                else
-                {
-                    newFolder = TreeNode$new(splitPath[[elementIndex]], "folder", NULL)
-                    newFolder$addChild(branch)
-                    branch = newFolder
-                }
-
-                branch$relativePath <- paste(unlist(splitPath[1:elementIndex]), collapse = "/")
-            }
-            
-            branch
-        },
-
-        addBranch = function(container, node)
-        {
-            child = container$getChild(node$name)
-
-            if(is.null(child))
-            {
-                container$addChild(node)
-            }
-            else
-            {
-                child$type = "folder"
-                private$addBranch(child, node$getFirstChild())
-            }
-        }
-    ),
-
-    cloneable = FALSE
-)
-
-TreeNode <- R6::R6Class(
-
-    "TreeNode",
-
-    public = list(
-
-        name         = NULL,
-        relativePath = NULL,
-        size         = NULL,
-        children     = NULL,
-        parent       = NULL,
-        type         = NULL,
-
-        initialize = function(name, type, size)
-        {
-            self$name <- name
-            self$type <- type
-            self$size <- size
-            self$children <- list()
-        },
-
-        addChild = function(node)
-        {
-            self$children <- c(self$children, node)
-            node$setParent(self)
-            self
-        },
-
-        setParent = function(parent)
-        {
-            self$parent = parent
-        },
-
-        getChild = function(childName)
-        {
-            for(child in self$children)
-            {
-                if(childName == child$name)
-                    return(child)
-            }
-
-            return(NULL)
-        },
-
-        hasChildren = function()
-        {
-            if(length(self$children) != 0)
-                return(TRUE)
-            else
-                return(FALSE)
-        },
-
-        getFirstChild = function()
-        {
-            if(!self$hasChildren())
-                return(NULL)
-            else
-                return(self$children[[1]])
-        }
-
-    ),
-
-    cloneable = FALSE
-)
diff --git a/sdk/R/R/HttpParser.R b/sdk/R/R/HttpParser.R
index faa22f0..dda3db9 100644
--- a/sdk/R/R/HttpParser.R
+++ b/sdk/R/R/HttpParser.R
@@ -14,26 +14,32 @@ HttpParser <- R6::R6Class(
             parsed_response <- httr::content(serverResponse, as = "parsed", type = "application/json")
         },
 
-        #Todo(Fudo): Test this.
+        #TODO rename this
         parseWebDAVResponse = function(response, uri)
         {
             text <- rawToChar(response$content)
             doc <- XML::xmlParse(text, asText=TRUE)
-
-            # calculate relative paths
             base <- paste(paste("/", strsplit(uri, "/")[[1]][-1:-3], sep="", collapse=""), "/", sep="")
-            result <- XML::xpathApply(doc, "//D:response", function(node) {
-                result = list()
-                children = XML::xmlChildren(node)
+            result <- unlist(
+                XML::xpathApply(doc, "//D:response/D:href", function(node) {
+                    sub(base, "", URLdecode(XML::xmlValue(node)), fixed=TRUE)
+                })
+            )
+            result <- result[result != ""]
+            result
+        },
 
-                result$name = sub(base, "", URLdecode(XML::xmlValue(children$href)), fixed=TRUE)
-                sizeXMLNode = XML::xmlChildren(XML::xmlChildren(children$propstat)$prop)$getcontentlength
-                result$fileSize = as.numeric(XML::xmlValue(sizeXMLNode))
+        extractFileSizeFromWebDAVResponse = function(response, uri)    
+        {
+            text <- rawToChar(response$content)
+            doc <- XML::xmlParse(text, asText=TRUE)
 
-                result
+            base <- paste(paste("/", strsplit(uri, "/")[[1]][-1:-3], sep="", collapse=""), "/", sep="")
+            result <- XML::xpathApply(doc, "//D:response/D:propstat/D:prop/D:getcontentlength", function(node) {
+              XML::xmlValue(node)
             })
 
-            result
+            unlist(result)
         }
     )
 )
diff --git a/sdk/R/R/Subcollection.R b/sdk/R/R/Subcollection.R
index 4fd2d3c..b453c53 100644
--- a/sdk/R/R/Subcollection.R
+++ b/sdk/R/R/Subcollection.R
@@ -9,35 +9,171 @@ Subcollection <- R6::R6Class(
 
     public = list(
 
-        initialize = function(name, relativePath, children)
+        initialize = function(name)
         {
-            private$name <- name
-            private$relativePath <- relativePath
-            private$children <- children
+            private$name       <- name
+            private$http       <- HttpRequest$new()
+            private$httpParser <- HttpParser$new()
         },
+        
+        add = function(content)
+        {
+            if("ArvadosFile"   %in% class(content) ||
+               "Subcollection" %in% class(content))
+            {
+                if(!is.null(content$.__enclos_env__$private$collection))
+                    stop("ArvadosFile/Subcollection already belongs to a collection.")
 
-        getName = function() private$name,
+                if(!is.null(private$collection))
+                {       
+                    contentPath <- paste0(self$getRelativePath(), "/", content$getFileList())
+                    private$collection$.__enclos_env__$private$createFilesOnREST(contentPath)
+                    content$.__enclos_env__$private$addToCollection(private$collection)
+                }
+
+                private$children <- c(private$children, content)
+                content$.__enclos_env__$private$parent = self
+            }
+            else
+            {
+                stop("Expected AravodsFile or Subcollection object, got ...")
+            }
+        },
+
+        removeFromCollection = function()
+        {
+            if(is.null(private$collection))
+                stop("Subcollection doesn't belong to any collection.")
+
+            collectionList <- paste0(self$getRelativePath(), "/", self$getFileList(fullpath = FALSE))
+            sapply(collectionList, function(file)
+            {
+                private$collection$.__enclos_env__$private$deleteFromREST(file)
+            })
+
+            #todo rename this add to a collection
+            private$addToCollection(NULL)
+            private$detachFromParent()
+
+        },
+
+        getFileList = function(fullpath = TRUE)
+        {
+            content <- NULL
 
-        getRelativePath = function() private$relativePath,
+            if(fullpath)
+            {
+                for(child in private$children)
+                    content <- c(content, child$getFileList())
+
+                if(private$name != "")
+                    content <- unlist(paste0(private$name, "/", content))
+            }
+            else
+            {
+                for(child in private$children)
+                    content <- c(content, child$getName())
+            }
+
+            content
+        },
 
         getSizeInBytes = function()
         {
-            overallSize = 0
-            for(child in private$children)
-                overallSize = overallSize + child$getSizeInBytes()
+            collectionURL <- URLencode(paste0(private$collection$api$getWebDavHostName(), "c=", private$collection$uuid))
+            subcollectionURL <- paste0(collectionURL, "/", self$getRelativePath(), "/");
+
+            headers = list("Authorization" = paste("OAuth2", private$collection$api$getToken()))
+
+            propfindResponse <- private$http$PROPFIND(subcollectionURL, headers)
 
-            overallSize
+            sizes <- private$httpParser$extractFileSizeFromWebDAVResponse(propfindResponse, collectionURL)
+            sizes <- as.numeric(sizes[-1])
+
+            sum(sizes)
         },
 
-        setParent = function(parent) private$parent <- parent
+        getName = function() private$name,
+
+        getRelativePath = function()
+        {
+            relativePath <- c(private$name)
+            parent <- private$parent
+
+            #Recurse back to root
+            while(!is.null(parent))
+            {
+                relativePath <- c(parent$getName(), relativePath)
+                parent <- parent$getParent()
+            }
+
+            relativePath <- relativePath[relativePath != ""]
+            paste0(relativePath, collapse = "/")
+        },
+
+        getParent = function() private$parent
     ),
 
     private = list(
 
-        name         = NULL,
-        relativePath = NULL,
-        children     = NULL,
-        parent       = NULL
+        name       = NULL,
+        children   = NULL,
+        parent     = NULL,
+        collection = NULL,
+        http       = NULL,
+        httpParser = NULL,
+
+        getChild = function(name)
+        {
+            for(child in private$children)
+            {
+                if(child$getName() == name)
+                    return(child)
+            }
+
+            return(NULL)
+        },
+
+        getFirstChild = function()
+        {
+            if(length(private$children) == 0)
+               return(NULL)
+
+            private$children[[1]]
+        },
+
+        removeChild = function(name)
+        {
+            numberOfChildren = length(private$children)
+            if(numberOfChildren > 0)
+            {
+                for(childIndex in 1:numberOfChildren)
+                {
+                    if(private$children[[childIndex]]$getName() == name)
+                    {
+                        private$children = private$children[-childIndex]
+                        return()
+                    }
+                }
+            }
+        },
+
+        addToCollection = function(collection)
+        {
+            for(child in private$children)
+                child$.__enclos_env__$private$addToCollection(collection)
+
+            private$collection = collection
+        },
+
+        detachFromParent = function()
+        {
+            if(!is.null(private$parent))
+            {
+                private$parent$.__enclos_env__$private$removeChild(private$name)
+                private$parent <- NULL
+            }
+        }
     ),
     
     cloneable = FALSE
diff --git a/sdk/R/README b/sdk/R/README
index c611c04..a59e9b5 100644
--- a/sdk/R/README
+++ b/sdk/R/README
@@ -55,12 +55,6 @@ collection <- Collection$new(arv, "uuid")
 
 --------------------------------------------------------------------------------------------------------------------------------
 
-#Print content of the collection (directory/folder tree structure)
-
-collection$printFileContent()
-
---------------------------------------------------------------------------------------------------------------------------------
-
 #Get file/folder content as character vector
 
 collection$getFileContent()
@@ -94,11 +88,26 @@ size <- arvadosSubcollection$getSizeInBytes()
 
 #Call structure
 
-collection$createNewFile("relativePath", "fileContent", "fileContentType")
+collection$add(arvadosFileOrSubcollectionOrFileName, optionalRelativePath)
 
 #Example
 
-collection$createNewFile("cpp/src/main.cpp", "#include<iostream>", "text/html")
+collection$add("main.cpp", "cpp/src/")
+
+#or
+
+folder <- Subcollection$new("src")
+file <- ArvadosFile$new("main.cpp")
+folder$add(file)
+
+collection$add(folder, "cpp")
+
+#Both examples will add file "main.cpp" in "./cpp/src/" folder if folder exists.
+#If subcollection contains more files or folders they will be added recursively.
+
+#You can also add multiple files
+
+collection$add(c("path/to/my/file.cpp", "path/to/other/file.cpp"))
 
 --------------------------------------------------------------------------------------------------------------------------------
 
@@ -109,3 +118,22 @@ arvadosFile <- collection$get("location/to/my/file.cpp")
 arvadosFile$write("This is new file content")
 
 --------------------------------------------------------------------------------------------------------------------------------
+
+#Delete file from a collection
+
+file <- collection$get("location/to/my/file.cpp")
+
+file$removeFromCollection()
+
+#Or
+
+collection$remove(file)
+
+#Both examples will remove file "file.cpp" from a collection
+#If subcollection contains more files or folders they will be removed recursively.
+
+#You can also remove multiple files
+
+collection$remove(c("path/to/my/file.cpp", "path/to/other/file.cpp"))
+
+--------------------------------------------------------------------------------------------------------------------------------
diff --git a/sdk/R/man/Collection.Rd b/sdk/R/man/CTest.Rd
similarity index 86%
copy from sdk/R/man/Collection.Rd
copy to sdk/R/man/CTest.Rd
index 46c76cb..6c14529 100644
--- a/sdk/R/man/Collection.Rd
+++ b/sdk/R/man/CTest.Rd
@@ -1,12 +1,12 @@
 % Generated by roxygen2: do not edit by hand
 % Please edit documentation in R/Collection.R
 \docType{data}
-\name{Collection}
-\alias{Collection}
+\name{CTest}
+\alias{CTest}
 \title{Arvados Collection Object}
 \format{An object of class \code{R6ClassGenerator} of length 24.}
 \usage{
-Collection
+CTest
 }
 \description{
 Update description
diff --git a/sdk/R/man/Collection.Rd b/sdk/R/man/Collection.Rd
index 46c76cb..2f54bfe 100644
--- a/sdk/R/man/Collection.Rd
+++ b/sdk/R/man/Collection.Rd
@@ -1,5 +1,5 @@
 % Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/Collection.R
+% Please edit documentation in R/CTest.R
 \docType{data}
 \name{Collection}
 \alias{Collection}
diff --git a/sdk/R/man/Collection.Rd b/sdk/R/man/CollectionTree.Rd
similarity index 70%
copy from sdk/R/man/Collection.Rd
copy to sdk/R/man/CollectionTree.Rd
index 46c76cb..adeed46 100644
--- a/sdk/R/man/Collection.Rd
+++ b/sdk/R/man/CollectionTree.Rd
@@ -1,12 +1,12 @@
 % Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/Collection.R
+% Please edit documentation in R/CollectionTree.R
 \docType{data}
-\name{Collection}
-\alias{Collection}
+\name{CollectionTree}
+\alias{CollectionTree}
 \title{Arvados Collection Object}
 \format{An object of class \code{R6ClassGenerator} of length 24.}
 \usage{
-Collection
+CollectionTree
 }
 \description{
 Update description

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list