Updated README and small fix for Subcollection docs.
[arvados.git] / sdk / R / R / Subcollection.R
1 source("./R/util.R")
2
3 #' Subcollection
4 #' 
5 #' Subcollection class represents a folder inside Arvados collection.
6 #' It is essentially a composite of arvadosFiles and other subcollections.
7 #' 
8 #' @section Usage:
9 #' \preformatted{subcollection = Subcollection$new(name)}
10 #'
11 #' @section Arguments:
12 #' \describe{
13 #'   \item{name}{Name of the subcollection.}
14 #' }
15 #' 
16 #' @section Methods:
17 #' \describe{
18 #'   \item{getName()}{Returns name of the subcollection.}
19 #'   \item{getRelativePath()}{Returns subcollection path relative to the root.}
20 #'   \item{add(content)}{Adds ArvadosFile or Subcollection specified by content to the subcollection.}
21 #'   \item{remove(name)}{Removes ArvadosFile or Subcollection specified by name from the subcollection.}
22 #'   \item{get(relativePath)}{If relativePath is valid, returns ArvadosFile or Subcollection specified by relativePath, else returns NULL.}
23 #'   \item{getFileListing()}{Returns subcollections file content as character vector.}
24 #'   \item{getSizeInBytes()}{Returns subcollections content size in bytes.}
25 #'   \item{move(newLocation)}{Moves subcollection to a new location inside collection.}
26 #' }
27 #'
28 #' @name Subcollection
29 #' @examples
30 #' \dontrun{
31 #' myFolder <- Subcollection$new("myFolder")
32 #' myFile   <- ArvadosFile$new("myFile")
33 #'
34 #' myFolder$add(myFile)
35 #' myFolder$get("myFile")
36 #' myFolder$remove("myFile")
37 #'
38 #' myFolder$move("newLocation/myFolder")
39 #' }
40 NULL
41
42 #' @export
43 Subcollection <- R6::R6Class(
44
45     "Subcollection",
46
47     public = list(
48
49         initialize = function(name)
50         {
51             private$name <- name
52         },
53
54         getName = function() private$name,
55         
56         getRelativePath = function()
57         {
58             relativePath <- c(private$name)
59             parent <- private$parent
60
61             while(!is.null(parent))
62             {
63                 relativePath <- c(parent$getName(), relativePath)
64                 parent <- parent$getParent()
65             }
66
67             relativePath <- relativePath[relativePath != ""]
68             paste0(relativePath, collapse = "/")
69         },
70
71         add = function(content)
72         {
73             if("ArvadosFile"   %in% class(content) ||
74                "Subcollection" %in% class(content))
75             {
76                 if(content$getName() == "")
77                     stop("Content has invalid name.")
78
79                 childWithSameName <- self$get(content$getName())
80
81                 if(!is.null(childWithSameName))
82                     stop(paste("Subcollection already contains ArvadosFile",
83                                "or Subcollection with same name."))
84
85                 if(!is.null(private$collection))
86                 {       
87                     if(self$getRelativePath() != "")
88                         contentPath <- paste0(self$getRelativePath(),
89                                               "/", content$getFileListing())
90                     else
91                         contentPath <- content$getFileListing()
92
93                     REST <- private$collection$getRESTService()
94                     REST$create(contentPath, private$collection$uuid)
95                     content$setCollection(private$collection)
96                 }
97
98                 private$children <- c(private$children, content)
99                 content$setParent(self)
100
101                 "Content added successfully."
102             }
103             else
104             {
105                 stop(paste0("Expected AravodsFile or Subcollection object, got ",
106                             paste0("(", paste0(class(content), collapse = ", "), ")"),
107                             "."))
108             }
109         },
110
111         remove = function(name)
112         {
113             if(is.character(name))
114             {
115                 child <- self$get(name)
116
117                 if(is.null(child))
118                     stop(paste("Subcollection doesn't contains ArvadosFile",
119                                "or Subcollection with specified name."))
120
121                 if(!is.null(private$collection))
122                 {
123                     REST <- private$collection$getRESTService()
124                     REST$delete(child$getRelativePath(), private$collection$uuid)
125
126                     child$setCollection(NULL)
127                 }
128
129                 private$removeChild(name)
130                 child$setParent(NULL)
131
132                 "Content removed"
133             }
134             else
135             {
136                 stop(paste0("Expected character, got ",
137                             paste0("(", paste0(class(name), collapse = ", "), ")"),
138                             "."))
139             }
140         },
141
142         getFileListing = function(fullPath = TRUE)
143         {
144             content <- private$getContentAsCharVector(fullPath)
145             content[order(tolower(content))]
146         },
147
148         getSizeInBytes = function()
149         {
150             if(is.null(private$collection))
151                 return(0)
152
153             REST <- private$collection$getRESTService()
154
155             fileSizes <- REST$getResourceSize(paste0(self$getRelativePath(), "/"),
156                                               private$collection$uuid)
157             return(sum(fileSizes))
158         },
159
160         move = function(newLocation)
161         {
162             if(is.null(private$collection))
163                 stop("Subcollection doesn't belong to any collection")
164
165             newLocation <- trimFromEnd(newLocation, "/")
166             nameAndPath <- splitToPathAndName(newLocation)
167
168             newParent <- private$collection$get(nameAndPath$path)
169
170             if(is.null(newParent))
171             {
172                 stop("Unable to get destination subcollection")
173             }
174
175             childWithSameName <- newParent$get(nameAndPath$name)
176
177             if(!is.null(childWithSameName))
178                 stop("Destination already contains content with same name.")
179
180             REST <- private$collection$getRESTService()
181             REST$move(self$getRelativePath(),
182                       paste0(newParent$getRelativePath(), "/", nameAndPath$name),
183                       private$collection$uuid)
184
185             private$dettachFromCurrentParent()
186             private$attachToNewParent(newParent)
187
188             private$name <- nameAndPath$name
189
190             "Content moved successfully."
191         },
192
193         get = function(name)
194         {
195             for(child in private$children)
196             {
197                 if(child$getName() == name)
198                     return(child)
199             }
200
201             return(NULL)
202         },
203
204         getFirst = function()
205         {
206             if(length(private$children) == 0)
207                return(NULL)
208
209             private$children[[1]]
210         },
211
212         setCollection = function(collection, setRecursively = TRUE)
213         {
214             private$collection = collection
215
216             if(setRecursively)
217             {
218                 for(child in private$children)
219                     child$setCollection(collection)
220             }
221         },
222
223         getCollection = function() private$collection,
224
225         getParent = function() private$parent,
226
227         setParent = function(newParent) private$parent <- newParent
228     ),
229
230     private = list(
231
232         name       = NULL,
233         children   = NULL,
234         parent     = NULL,
235         collection = NULL,
236
237         removeChild = function(name)
238         {
239             numberOfChildren = length(private$children)
240             if(numberOfChildren > 0)
241             {
242                 for(childIndex in 1:numberOfChildren)
243                 {
244                     if(private$children[[childIndex]]$getName() == name)
245                     {
246                         private$children = private$children[-childIndex]
247                         return()
248                     }
249                 }
250             }
251         },
252
253         attachToNewParent = function(newParent)
254         {
255             #Note: We temporary set parents collection to NULL. This will ensure that
256             #      add method doesn't post file on REST.
257             parentsCollection <- newParent$getCollection()
258             newParent$setCollection(NULL, setRecursively = FALSE)
259
260             newParent$add(self)
261
262             newParent$setCollection(parentsCollection, setRecursively = FALSE)
263
264             private$parent <- newParent
265         },
266
267         dettachFromCurrentParent = function()
268         {
269             #Note: We temporary set parents collection to NULL. This will ensure that
270             #      remove method doesn't remove this subcollection from REST.
271             parent <- private$parent
272             parentsCollection <- parent$getCollection()
273             parent$setCollection(NULL, setRecursively = FALSE)
274
275             parent$remove(private$name)
276
277             parent$setCollection(parentsCollection, setRecursively = FALSE)
278         },
279
280         getContentAsCharVector = function(fullPath = TRUE)
281         {
282             content <- NULL
283
284             if(fullPath)
285             {
286                 for(child in private$children)
287                     content <- c(content, child$getFileListing())
288
289                 if(private$name != "")
290                     content <- unlist(paste0(private$name, "/", content))
291             }
292             else
293             {
294                 for(child in private$children)
295                     content <- c(content, child$getName())
296             }
297
298             content
299         }
300     ),
301     
302     cloneable = FALSE
303 )
304
305 #' print.Subcollection
306 #'
307 #' Custom print function for Subcollection class
308 #'
309 #' @param x Instance of Subcollection class
310 #' @param ... Optional arguments.
311 #' @export 
312 print.Subcollection = function(x, ...)
313 {
314     collection   <- NULL
315     relativePath <- x$getRelativePath()
316
317     if(!is.null(x$getCollection()))
318     {
319         collection <- x$getCollection()$uuid
320
321         if(!x$getName() == "")
322             relativePath <- paste0("/", relativePath)
323     }
324
325     cat(paste0("Type:          ", "\"", "Arvados Subcollection", "\""), sep = "\n")
326     cat(paste0("Name:          ", "\"", x$getName(),             "\""), sep = "\n")
327     cat(paste0("Relative path: ", "\"", relativePath,            "\""), sep = "\n")
328     cat(paste0("Collection:    ", "\"", collection,              "\""), sep = "\n")
329 }