21700: Install Bundler system-wide in Rails postinst
[arvados.git] / sdk / java-v2 / src / main / java / org / arvados / client / facade / ArvadosFacade.java
1 /*
2  * Copyright (C) The Arvados Authors. All rights reserved.
3  *
4  * SPDX-License-Identifier: AGPL-3.0 OR Apache-2.0
5  *
6  */
7
8 package org.arvados.client.facade;
9
10 import com.google.common.collect.Lists;
11 import org.arvados.client.api.client.CollectionsApiClient;
12 import org.arvados.client.api.client.GroupsApiClient;
13 import org.arvados.client.api.client.KeepWebApiClient;
14 import org.arvados.client.api.client.UsersApiClient;
15 import org.arvados.client.api.model.*;
16 import org.arvados.client.api.model.argument.Filter;
17 import org.arvados.client.api.model.argument.ListArgument;
18 import org.arvados.client.config.FileConfigProvider;
19 import org.arvados.client.config.ConfigProvider;
20 import org.arvados.client.logic.collection.FileToken;
21 import org.arvados.client.logic.collection.ManifestDecoder;
22 import org.arvados.client.logic.keep.FileDownloader;
23 import org.arvados.client.logic.keep.FileUploader;
24 import org.arvados.client.logic.keep.KeepClient;
25 import org.slf4j.Logger;
26
27 import java.io.File;
28 import java.util.Arrays;
29 import java.util.Collections;
30 import java.util.List;
31 import java.util.Map;
32
33 public class ArvadosFacade {
34
35     private final ConfigProvider config;
36     private final Logger log = org.slf4j.LoggerFactory.getLogger(ArvadosFacade.class);
37     private CollectionsApiClient collectionsApiClient;
38     private GroupsApiClient groupsApiClient;
39     private UsersApiClient usersApiClient;
40     private FileDownloader fileDownloader;
41     private FileUploader fileUploader;
42     private static final String PROJECT = "project";
43     private static final String SUBPROJECT = "sub-project";
44
45     public ArvadosFacade(ConfigProvider config) {
46         this.config = config;
47         setFacadeFields();
48     }
49
50     public ArvadosFacade() {
51         this.config = new FileConfigProvider();
52         setFacadeFields();
53     }
54
55     private void setFacadeFields() {
56         collectionsApiClient = new CollectionsApiClient(config);
57         groupsApiClient = new GroupsApiClient(config);
58         usersApiClient = new UsersApiClient(config);
59         KeepClient keepClient = new KeepClient(config);
60         ManifestDecoder manifestDecoder = new ManifestDecoder();
61         KeepWebApiClient keepWebApiClient = new KeepWebApiClient(config);
62         fileDownloader = new FileDownloader(keepClient, manifestDecoder, collectionsApiClient, keepWebApiClient);
63         fileUploader = new FileUploader(keepClient, collectionsApiClient, config);
64     }
65
66     /**
67      * This method downloads single file from collection using Arvados Keep-Web.
68      * File is saved on a drive in specified location and returned.
69      *
70      * @param filePathName         path to the file in collection. If requested file is stored
71      *                             directly in collection (not within its subdirectory) this
72      *                             would be just the name of file (ex. 'file.txt').
73      *                             Otherwise full file path must be passed (ex. 'folder/file.txt')
74      * @param collectionUuid       uuid of collection containing requested file
75      * @param pathToDownloadFolder path to location in which file should be saved.
76      *                             Passed location must be a directory in which file of
77      *                             that name does not already exist.
78      * @return downloaded file
79      */
80     public File downloadFile(String filePathName, String collectionUuid, String pathToDownloadFolder) {
81         return fileDownloader.downloadSingleFileUsingKeepWeb(filePathName, collectionUuid, pathToDownloadFolder);
82     }
83
84     /**
85      * This method downloads all files from collection.
86      * Directory named by collection uuid is created in specified location,
87      * files are saved on a drive in this directory and list with downloaded
88      * files is returned.
89      *
90      * @param collectionUuid       uuid of collection from which files are downloaded
91      * @param pathToDownloadFolder path to location in which files should be saved.
92      *                             New folder named by collection uuid, containing
93      *                             downloaded files, is created in this location.
94      *                             Passed location must be a directory in which folder
95      *                             of that name does not already exist.
96      * @param usingKeepWeb         if set to true files will be downloaded using Keep Web.
97      *                             If set to false files will be downloaded using Keep Server API.
98      * @return list containing downloaded files
99      */
100     public List<File> downloadCollectionFiles(String collectionUuid, String pathToDownloadFolder, boolean usingKeepWeb) {
101         if (usingKeepWeb)
102             return fileDownloader.downloadFilesFromCollectionUsingKeepWeb(collectionUuid, pathToDownloadFolder);
103         return fileDownloader.downloadFilesFromCollection(collectionUuid, pathToDownloadFolder);
104     }
105
106     /**
107      * Lists all FileTokens (objects containing information about files) for
108      * specified collection.
109      * Information in each FileToken includes file path, name, size and position
110      * in data stream
111      *
112      * @param collectionUuid uuid of collection for which FileTokens are listed
113      * @return list containing FileTokens for each file in specified collection
114      */
115     public List<FileToken> listFileInfoFromCollection(String collectionUuid) {
116         return fileDownloader.listFileInfoFromCollection(collectionUuid);
117     }
118
119     /**
120      * Creates and uploads new collection containing passed files.
121      * Created collection has a default name and is uploaded to user's 'Home' project.
122      *
123      * @see ArvadosFacade#upload(List, String, String)
124      * @param files    list of files to be uploaded within new collection
125      * @return collection object mapped from JSON that is returned from server after successful upload
126      */
127     public Collection upload(List<File> files) {
128         return upload(files, null, null);
129     }
130
131     /**
132      * Creates and uploads new collection containing a single file.
133      * Created collection has a default name and is uploaded to user's 'Home' project.
134      *
135      * @see ArvadosFacade#upload(List, String, String)
136      * @param file file to be uploaded
137      * @return collection object mapped from JSON that is returned from server after successful upload
138      */
139     public Collection upload(File file) {
140         return upload(Collections.singletonList(file), null, null);
141     }
142
143     /**
144      * Uploads new collection with specified name and containing selected files
145      * to an existing project.
146      *
147      * @param sourceFiles    list of files to be uploaded within new collection
148      * @param collectionName name for the newly created collection.
149      *                       Collection with that name cannot be already created
150      *                       in specified project. If null is passed
151      *                       then collection name is set to default, containing
152      *                       phrase 'New Collection' and a timestamp.
153      * @param projectUuid    uuid of the project in which created collection is to be included.
154      *                       If null is passed then collection is uploaded to user's 'Home' project.
155      * @return collection object mapped from JSON that is returned from server after successful upload
156      */
157     public Collection upload(List<File> sourceFiles, String collectionName, String projectUuid) {
158         return fileUploader.upload(sourceFiles, collectionName, projectUuid);
159     }
160
161     /**
162      * Uploads a file to a specified collection.
163      *
164      * @see ArvadosFacade#uploadToExistingCollection(List, String)
165      * @param file           file to be uploaded to existing collection. Filenames must be unique
166      *                       in comparison with files already existing within collection.
167      * @param collectionUUID UUID of collection to which files should be uploaded
168      * @return collection object mapped from JSON that is returned from server after successful upload
169      */
170     public Collection uploadToExistingCollection(File file, String collectionUUID) {
171         return fileUploader.uploadToExistingCollection(Collections.singletonList(file), collectionUUID);
172     }
173
174     /**
175      * Uploads multiple files to an existing collection.
176      *
177      * @param files          list of files to be uploaded to existing collection.
178      *                       File names must be unique - both within passed list and
179      *                       in comparison with files already existing within collection.
180      * @param collectionUUID UUID of collection to which files should be uploaded
181      * @return collection object mapped from JSON that is returned from server after successful upload
182      */
183     public Collection uploadToExistingCollection(List<File> files, String collectionUUID) {
184         return fileUploader.uploadToExistingCollection(files, collectionUUID);
185     }
186
187     /**
188      * Creates and uploads new empty collection to specified project.
189      *
190      * @param collectionName name for the newly created collection.
191      *                       Collection with that name cannot be already created
192      *                       in specified project.
193      * @param projectUuid    uuid of project that will contain uploaded empty collection.
194      *                       To select home project pass current user's uuid from getCurrentUser()
195      * @return collection object mapped from JSON that is returned from server after successful upload
196      * @see ArvadosFacade#getCurrentUser()
197      */
198     public Collection createEmptyCollection(String collectionName, String projectUuid) {
199         Collection collection = new Collection();
200         collection.setOwnerUuid(projectUuid);
201         collection.setName(collectionName);
202         return collectionsApiClient.create(collection);
203     }
204
205     /**
206      * Uploads multiple files to an existing collection.
207      *
208      * @param collectionUUID UUID of collection to which the files are to be copied
209      * @param files          map of files to be copied to existing collection.
210      *                       The map consists of a pair in the form of a filename and a filename
211      *                       along with the Portable data hash
212      * @return collection object mapped from JSON that is returned from server after successful copied
213      */
214     public Collection updateWithReplaceFiles(String collectionUUID, Map<String, String> files) {
215         CollectionReplaceFiles replaceFilesRequest = new CollectionReplaceFiles();
216         replaceFilesRequest.getReplaceFiles().putAll(files);
217         return collectionsApiClient.update(collectionUUID, replaceFilesRequest);
218     }
219
220     /**
221      * Returns current user information based on Api Token provided via configuration
222      *
223      * @return user object mapped from JSON that is returned from server based on provided Api Token.
224      * It contains information about user who has this token assigned.
225      */
226     public User getCurrentUser() {
227         return usersApiClient.current();
228     }
229
230     /**
231      * Gets uuid of current user based on api Token provided in configuration and uses it to list all
232      * projects that this user owns in Arvados.
233      *
234      * @return GroupList containing all groups that current user is owner of.
235      * @see ArvadosFacade#getCurrentUser()
236      */
237     public GroupList showGroupsOwnedByCurrentUser() {
238         ListArgument listArgument = ListArgument.builder()
239                 .filters(Arrays.asList(
240                         Filter.of("owner_uuid", Filter.Operator.LIKE, getCurrentUser().getUuid()),
241                         Filter.of("group_class", Filter.Operator.IN, Lists.newArrayList(PROJECT, SUBPROJECT)
242                         )))
243                 .build();
244         GroupList groupList = groupsApiClient.list(listArgument);
245         log.debug("Groups owned by user:");
246         groupList.getItems().forEach(m -> log.debug(m.getUuid() + " -- " + m.getName()));
247
248         return groupList;
249     }
250
251     /**
252      * Gets uuid of current user based on api Token provided in configuration and uses it to list all
253      * projects that this user has read access to in Arvados.
254      *
255      * @return GroupList containing all groups that current user has read access to.
256      */
257     public GroupList showGroupsAccessibleByCurrentUser() {
258         ListArgument listArgument = ListArgument.builder()
259                 .filters(Collections.singletonList(
260                         Filter.of("group_class", Filter.Operator.IN, Lists.newArrayList(PROJECT, SUBPROJECT)
261                         )))
262                 .build();
263         GroupList groupList = groupsApiClient.list(listArgument);
264         log.debug("Groups accessible by user:");
265         groupList.getItems().forEach(m -> log.debug(m.getUuid() + " -- " + m.getName()));
266
267         return groupList;
268     }
269
270     /**
271      * Filters all collections from selected project and returns list of those that contain passed String in their name.
272      * Operator "LIKE" is used so in order to obtain certain collection it is sufficient to pass just part of its name.
273      * Returned collections in collectionList are ordered by date of creation (starting from oldest one).
274      *
275      * @param collectionName collections containing this param in their name will be returned.
276      *                       Passing a wildcard is possible - for example passing "a%" searches for
277      *                       all collections starting with "a".
278      * @param projectUuid    uuid of project in which will be searched for collections with given name. To search home
279      *                       project provide user uuid (from getCurrentUser())
280      * @return object CollectionList containing all collections matching specified name criteria
281      * @see ArvadosFacade#getCurrentUser()
282      */
283     public CollectionList getCollectionsFromProjectByName(String collectionName, String projectUuid) {
284         ListArgument listArgument = ListArgument.builder()
285                 .filters(Arrays.asList(
286                         Filter.of("owner_uuid", Filter.Operator.LIKE, projectUuid),
287                         Filter.of("name", Filter.Operator.LIKE, collectionName)
288                 ))
289                 .order(Collections.singletonList("created_at"))
290                 .build();
291
292         return collectionsApiClient.list(listArgument);
293     }
294
295     /**
296      * Gets project details by uuid.
297      *
298      * @param projectUuid uuid of project
299      * @return Group object containing information about project
300      */
301     public Group getProjectByUuid(String projectUuid) {
302         Group project = groupsApiClient.get(projectUuid);
303         log.debug("Retrieved " + project.getName() + " with UUID: " + project.getUuid());
304         return project;
305     }
306
307     /**
308      * Creates new project that will be a subproject of "home" for current user.
309      *
310      * @param projectName name for the newly created project
311      * @return Group object containing information about created project
312      * (mapped from JSON returned from server after creating the project)
313      */
314     public Group createNewProject(String projectName) {
315         Group project = new Group();
316         project.setName(projectName);
317         project.setGroupClass(PROJECT);
318         Group createdProject = groupsApiClient.create(project);
319         log.debug("Project " + createdProject.getName() + " created with UUID: " + createdProject.getUuid());
320         return createdProject;
321     }
322
323     /**
324      * Deletes collection with specified uuid.
325      *
326      * @param collectionUuid uuid of collection to be deleted. User whose token is provided in configuration
327      *                       must be authorized to delete such collection.
328      * @return collection object with deleted collection (mapped from JSON returned from server after deleting the collection)
329      */
330     public Collection deleteCollection(String collectionUuid) {
331         Collection deletedCollection = collectionsApiClient.delete(collectionUuid);
332         log.debug("Collection: " + collectionUuid + " deleted.");
333         return deletedCollection;
334     }
335 }