001package com.box.sdk; 002 003import static com.box.sdk.PagingParameters.DEFAULT_LIMIT; 004import static com.box.sdk.PagingParameters.marker; 005import static com.box.sdk.SortParameters.none; 006 007import com.eclipsesource.json.Json; 008import com.eclipsesource.json.JsonObject; 009import java.net.URL; 010import java.util.Iterator; 011 012/** 013 * Provides methods for deleting, recovering, and viewing a user's trashed files and folders. 014 * 015 * <p>Unless otherwise noted, the methods in this class can throw an unchecked {@link 016 * BoxAPIException} (unchecked meaning that the compiler won't force you to handle it) if an error 017 * occurs. If you wish to implement custom error handling for errors related to the Box REST API, 018 * you should capture this exception explicitly. 019 */ 020public class BoxTrash implements Iterable<BoxItem.Info> { 021 022 /** Get Item URL Template. */ 023 public static final URLTemplate GET_ITEMS_URL = new URLTemplate("folders/trash/items/"); 024 /** Folder Info URL Template. */ 025 public static final URLTemplate FOLDER_INFO_URL_TEMPLATE = new URLTemplate("folders/%s/trash"); 026 /** File Info URL Template. */ 027 public static final URLTemplate FILE_INFO_URL_TEMPLATE = new URLTemplate("files/%s/trash"); 028 /** Restore File URL Template. */ 029 public static final URLTemplate RESTORE_FILE_URL_TEMPLATE = new URLTemplate("files/%s"); 030 /** Restore Folder URL Template. */ 031 public static final URLTemplate RESTORE_FOLDER_URL_TEMPLATE = new URLTemplate("folders/%s"); 032 033 private final BoxAPIConnection api; 034 035 /** 036 * Constructs a BoxTrash using a given API connection. 037 * 038 * @param api the API connection to be used by the trash. 039 */ 040 public BoxTrash(BoxAPIConnection api) { 041 this.api = api; 042 } 043 044 /** 045 * Permanently deletes a trashed folder. 046 * 047 * @param folderID the ID of the trashed folder to permanently delete. 048 */ 049 public void deleteFolder(String folderID) { 050 URL url = FOLDER_INFO_URL_TEMPLATE.build(this.api.getBaseURL(), folderID); 051 BoxAPIRequest request = new BoxAPIRequest(this.api, url, "DELETE"); 052 request.send().close(); 053 } 054 055 /** 056 * Gets information about a trashed folder. 057 * 058 * @param folderID the ID of the trashed folder. 059 * @return info about the trashed folder. 060 */ 061 public BoxFolder.Info getFolderInfo(String folderID) { 062 URL url = FOLDER_INFO_URL_TEMPLATE.build(this.api.getBaseURL(), folderID); 063 BoxJSONRequest request = new BoxJSONRequest(this.api, url, "GET"); 064 try (BoxJSONResponse response = request.send()) { 065 JsonObject jsonObject = Json.parse(response.getJSON()).asObject(); 066 067 BoxFolder folder = new BoxFolder(this.api, jsonObject.get("id").asString()); 068 return folder.new Info(response.getJSON()); 069 } 070 } 071 072 /** 073 * Gets information about a trashed folder that's limited to a list of specified fields. 074 * 075 * @param folderID the ID of the trashed folder. 076 * @param fields the fields to retrieve. 077 * @return info about the trashed folder containing only the specified fields. 078 */ 079 public BoxFolder.Info getFolderInfo(String folderID, String... fields) { 080 String queryString = new QueryStringBuilder().appendParam("fields", fields).toString(); 081 URL url = FOLDER_INFO_URL_TEMPLATE.buildWithQuery(this.api.getBaseURL(), queryString, folderID); 082 BoxJSONRequest request = new BoxJSONRequest(this.api, url, "GET"); 083 try (BoxJSONResponse response = request.send()) { 084 JsonObject jsonObject = Json.parse(response.getJSON()).asObject(); 085 086 BoxFolder folder = new BoxFolder(this.api, jsonObject.get("id").asString()); 087 return folder.new Info(response.getJSON()); 088 } 089 } 090 091 /** 092 * Restores a trashed folder back to its original location. 093 * 094 * @param folderID the ID of the trashed folder. 095 * @return info about the restored folder. 096 */ 097 public BoxFolder.Info restoreFolder(String folderID) { 098 URL url = RESTORE_FOLDER_URL_TEMPLATE.build(this.api.getBaseURL(), folderID); 099 BoxJSONRequest request = new BoxJSONRequest(this.api, url, "POST"); 100 JsonObject requestJSON = new JsonObject().add("", ""); 101 request.setBody(requestJSON.toString()); 102 try (BoxJSONResponse response = request.send()) { 103 JsonObject responseJSON = Json.parse(response.getJSON()).asObject(); 104 105 BoxFolder restoredFolder = new BoxFolder(this.api, responseJSON.get("id").asString()); 106 return restoredFolder.new Info(responseJSON); 107 } 108 } 109 110 /** 111 * Restores a trashed folder to a new location with a new name. 112 * 113 * @param folderID the ID of the trashed folder. 114 * @param newName an optional new name to give the folder. This can be null to use the folder's 115 * original name. 116 * @param newParentID an optional new parent ID for the folder. This can be null to use the 117 * folder's original parent. 118 * @return info about the restored folder. 119 */ 120 public BoxFolder.Info restoreFolder(String folderID, String newName, String newParentID) { 121 JsonObject requestJSON = new JsonObject(); 122 123 if (newName != null) { 124 requestJSON.add("name", newName); 125 } 126 127 if (newParentID != null) { 128 JsonObject parent = new JsonObject(); 129 parent.add("id", newParentID); 130 requestJSON.add("parent", parent); 131 } 132 133 URL url = RESTORE_FOLDER_URL_TEMPLATE.build(this.api.getBaseURL(), folderID); 134 BoxJSONRequest request = new BoxJSONRequest(this.api, url, "POST"); 135 request.setBody(requestJSON.toString()); 136 try (BoxJSONResponse response = request.send()) { 137 JsonObject responseJSON = Json.parse(response.getJSON()).asObject(); 138 139 BoxFolder restoredFolder = new BoxFolder(this.api, responseJSON.get("id").asString()); 140 return restoredFolder.new Info(responseJSON); 141 } 142 } 143 144 /** 145 * Permanently deletes a trashed file. 146 * 147 * @param fileID the ID of the trashed folder to permanently delete. 148 */ 149 public void deleteFile(String fileID) { 150 URL url = FILE_INFO_URL_TEMPLATE.build(this.api.getBaseURL(), fileID); 151 BoxAPIRequest request = new BoxAPIRequest(this.api, url, "DELETE"); 152 request.send().close(); 153 } 154 155 /** 156 * Gets information about a trashed file. 157 * 158 * @param fileID the ID of the trashed file. 159 * @return info about the trashed file. 160 */ 161 public BoxFile.Info getFileInfo(String fileID) { 162 URL url = FILE_INFO_URL_TEMPLATE.build(this.api.getBaseURL(), fileID); 163 BoxJSONRequest request = new BoxJSONRequest(this.api, url, "GET"); 164 try (BoxJSONResponse response = request.send()) { 165 JsonObject jsonObject = Json.parse(response.getJSON()).asObject(); 166 167 BoxFile file = new BoxFile(this.api, jsonObject.get("id").asString()); 168 return file.new Info(response.getJSON()); 169 } 170 } 171 172 /** 173 * Gets information about a trashed file that's limited to a list of specified fields. 174 * 175 * @param fileID the ID of the trashed file. 176 * @param fields the fields to retrieve. 177 * @return info about the trashed file containing only the specified fields. 178 */ 179 public BoxFile.Info getFileInfo(String fileID, String... fields) { 180 String queryString = new QueryStringBuilder().appendParam("fields", fields).toString(); 181 URL url = FILE_INFO_URL_TEMPLATE.buildWithQuery(this.api.getBaseURL(), queryString, fileID); 182 BoxJSONRequest request = new BoxJSONRequest(this.api, url, "GET"); 183 try (BoxJSONResponse response = request.send()) { 184 JsonObject jsonObject = Json.parse(response.getJSON()).asObject(); 185 186 BoxFile file = new BoxFile(this.api, jsonObject.get("id").asString()); 187 return file.new Info(response.getJSON()); 188 } 189 } 190 191 /** 192 * Restores a trashed file back to its original location. 193 * 194 * @param fileID the ID of the trashed file. 195 * @return info about the restored file. 196 */ 197 public BoxFile.Info restoreFile(String fileID) { 198 URL url = RESTORE_FILE_URL_TEMPLATE.build(this.api.getBaseURL(), fileID); 199 BoxJSONRequest request = new BoxJSONRequest(this.api, url, "POST"); 200 JsonObject requestJSON = new JsonObject().add("", ""); 201 return getInfo(requestJSON, request); 202 } 203 204 /** 205 * Restores a trashed file to a new location with a new name. 206 * 207 * @param fileID the ID of the trashed file. 208 * @param newName an optional new name to give the file. This can be null to use the file's 209 * original name. 210 * @param newParentID an optional new parent ID for the file. This can be null to use the file's 211 * original parent. 212 * @return info about the restored file. 213 */ 214 public BoxFile.Info restoreFile(String fileID, String newName, String newParentID) { 215 JsonObject requestJSON = new JsonObject(); 216 217 if (newName != null) { 218 requestJSON.add("name", newName); 219 } 220 221 if (newParentID != null) { 222 JsonObject parent = new JsonObject(); 223 parent.add("id", newParentID); 224 requestJSON.add("parent", parent); 225 } 226 227 URL url = RESTORE_FILE_URL_TEMPLATE.build(this.api.getBaseURL(), fileID); 228 BoxJSONRequest request = new BoxJSONRequest(this.api, url, "POST"); 229 return getInfo(requestJSON, request); 230 } 231 232 /** 233 * Returns an iterator over the items in the trash. 234 * 235 * @return an iterator over the items in the trash. 236 */ 237 public Iterator<BoxItem.Info> iterator() { 238 return items(none(), marker(DEFAULT_LIMIT)).iterator(); 239 } 240 241 /** 242 * Returns an iterable containing the items in trash. You can specify sort order, limit of files 243 * requested, ofset or use marker based pagination. 244 * 245 * @param sortParameters describes sorting parameters. Sort parameters are supported only with 246 * offset based pagination. Use {@link SortParameters#none()} to ignore sorting. 247 * @param pagingParameters describes paging parameters 248 * @param fields the fields to retrieve. 249 * @return an iterable containing the items in the trash. 250 */ 251 public Iterable<BoxItem.Info> items( 252 SortParameters sortParameters, PagingParameters pagingParameters, String... fields) { 253 QueryStringBuilder builder = sortParameters.asQueryStringBuilder(); 254 validateSortIsSelectedWithOffsetPaginationOnly(pagingParameters, builder); 255 256 if (fields.length > 0) { 257 builder.appendParam("fields", fields); 258 } 259 final String query = builder.toString(); 260 return () -> { 261 URL url = GET_ITEMS_URL.buildWithQuery(this.api.getBaseURL(), query); 262 if (pagingParameters == null) { 263 return new BoxItemIterator(this.api, url, marker(DEFAULT_LIMIT)); 264 } else { 265 return new BoxItemIterator(this.api, url, pagingParameters); 266 } 267 }; 268 } 269 270 private BoxFile.Info getInfo(JsonObject requestJSON, BoxJSONRequest request) { 271 request.setBody(requestJSON.toString()); 272 try (BoxJSONResponse response = request.send()) { 273 JsonObject responseJSON = Json.parse(response.getJSON()).asObject(); 274 275 BoxFile restoredFile = new BoxFile(this.api, responseJSON.get("id").asString()); 276 return restoredFile.new Info(responseJSON); 277 } 278 } 279 280 /** 281 * Throws IllegalArgumentException exception when sorting and marker pagination is selected. 282 * 283 * @param pagingParameters paging definition to check 284 * @param sortQuery builder containing sort query 285 */ 286 private void validateSortIsSelectedWithOffsetPaginationOnly( 287 PagingParameters pagingParameters, QueryStringBuilder sortQuery) { 288 if (pagingParameters != null 289 && pagingParameters.isMarkerBasedPaging() 290 && sortQuery.toString().length() > 0) { 291 throw new IllegalArgumentException( 292 "Sorting is not supported when using marker based pagination."); 293 } 294 } 295}