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