001package com.box.sdk;
002
003import com.eclipsesource.json.Json;
004import com.eclipsesource.json.JsonObject;
005import com.eclipsesource.json.JsonValue;
006import java.io.IOException;
007import java.io.InputStream;
008import java.io.OutputStream;
009import java.net.URL;
010import java.text.ParseException;
011import java.util.Date;
012
013/**
014 * Represents a particular version of a file on Box.
015 */
016@BoxResourceType("file_version")
017public class BoxFileVersion extends BoxResource {
018    /**
019     * Content URL Template.
020     */
021    public static final URLTemplate CONTENT_URL_TEMPLATE = new URLTemplate("files/%s/content?version=%s");
022    /**
023     * Version URL Template.
024     */
025    public static final URLTemplate VERSION_URL_TEMPLATE = new URLTemplate("files/%s/versions/%s");
026    private static final int BUFFER_SIZE = 8192;
027
028    private String fileID;
029
030    private String versionID;
031    private String sha1;
032    private String name;
033    private long size;
034    private String uploaderDisplayName;
035    private Date createdAt;
036    private Date modifiedAt;
037    private BoxUser.Info modifiedBy;
038    private Date trashedAt;
039    private BoxUser.Info trashedBy;
040    private Date restoredAt;
041    private BoxUser.Info restoredBy;
042    private Date purgedAt;
043    private Long versionNumber;
044
045    /**
046     * Constructs a BoxFileVersion from a JSON string.
047     *
048     * @param api    the API connection to be used by the file.
049     * @param json   the JSON encoded file version.
050     * @param fileID the ID of the file.
051     */
052    public BoxFileVersion(BoxAPIConnection api, String json, String fileID) {
053        this(api, Json.parse(json).asObject(), fileID);
054    }
055
056    BoxFileVersion(BoxAPIConnection api, JsonObject jsonObject, String fileID) {
057        super(api, jsonObject.get("id").asString());
058
059        this.fileID = fileID;
060        this.parseJSON(jsonObject);
061    }
062
063    /**
064     * Method used to update fields with values received from API.
065     *
066     * @param jsonObject JSON-encoded info about File Version object.
067     */
068    private void parseJSON(JsonObject jsonObject) {
069        for (JsonObject.Member member : jsonObject) {
070            JsonValue value = member.getValue();
071            if (value.isNull()) {
072                continue;
073            }
074
075            try {
076                String memberName = member.getName();
077                if (memberName.equals("id")) {
078                    this.versionID = value.asString();
079                } else if (memberName.equals("sha1")) {
080                    this.sha1 = value.asString();
081                } else if (memberName.equals("name")) {
082                    this.name = value.asString();
083                } else if (memberName.equals("size")) {
084                    this.size = Double.valueOf(value.toString()).longValue();
085                } else if (memberName.equals("uploader_display_name")) {
086                    this.uploaderDisplayName = value.asString();
087                } else if (memberName.equals("created_at")) {
088                    this.createdAt = BoxDateFormat.parse(value.asString());
089                } else if (memberName.equals("modified_at")) {
090                    this.modifiedAt = BoxDateFormat.parse(value.asString());
091                } else if (memberName.equals("trashed_at")) {
092                    this.trashedAt = BoxDateFormat.parse(value.asString());
093                } else if (memberName.equals("trashed_by")) {
094                    JsonObject userJSON = value.asObject();
095                    String userID = userJSON.get("id").asString();
096                    BoxUser user = new BoxUser(getAPI(), userID);
097                    this.trashedBy = user.new Info(userJSON);
098                } else if (memberName.equals("modified_by")) {
099                    JsonObject userJSON = value.asObject();
100                    String userID = userJSON.get("id").asString();
101                    BoxUser user = new BoxUser(getAPI(), userID);
102                    this.modifiedBy = user.new Info(userJSON);
103                } else if (memberName.equals("restored_at")) {
104                    this.restoredAt = BoxDateFormat.parse(value.asString());
105                } else if (memberName.equals("restored_by")) {
106                    JsonObject userJSON = value.asObject();
107                    String userID = userJSON.get("id").asString();
108                    BoxUser user = new BoxUser(getAPI(), userID);
109                    this.restoredBy = user.new Info(userJSON);
110                } else if (memberName.equals("purged_at")) {
111                    this.purgedAt = BoxDateFormat.parse(value.asString());
112                } else if (memberName.equals("version_number")) {
113                    this.versionNumber = Long.parseLong(value.asString());
114                }
115            } catch (ParseException e) {
116                assert false : "A ParseException indicates a bug in the SDK.";
117            }
118        }
119    }
120
121    /**
122     * @return the file id this file version belongs to.
123     */
124    public String getFileID() {
125        return this.fileID;
126    }
127
128    /**
129     * Used if no or wrong file id was set with constructor.
130     *
131     * @param fileID the file id this file version belongs to.
132     */
133    public void setFileID(String fileID) {
134        this.fileID = fileID;
135    }
136
137    /**
138     * Gets the version ID of this version of the file.
139     *
140     * @return the version ID of this version of the file.
141     */
142    public String getVersionID() {
143        return this.versionID;
144    }
145
146    /**
147     * Gets the SHA1 hash of this version of the file.
148     *
149     * @return the SHA1 hash of this version of the file.
150     */
151    public String getSha1() {
152        return this.sha1;
153    }
154
155    /**
156     * Gets the name of this version of the file.
157     *
158     * @return the name of this version of the file.
159     */
160    public String getName() {
161        return this.name;
162    }
163
164    /**
165     * Gets the size of this version of the file.
166     *
167     * @return the size of this version of the file.
168     */
169    public long getSize() {
170        return this.size;
171    }
172
173    /**
174     * Gets the time that this version of the file was created.
175     *
176     * @return the time that this version of the file was created.
177     */
178    public Date getCreatedAt() {
179        return this.createdAt;
180    }
181
182    /**
183     * Gets the user's name at the time of upload.
184     *
185     * @return the time user's name at the time of upload.
186     */
187    public String getUploaderDisplayName() {
188        return this.uploaderDisplayName;
189    }
190
191    /**
192     * Gets the time that this version of the file was modified.
193     *
194     * @return the time that this version of the file was modified.
195     */
196    public Date getModifiedAt() {
197        return this.modifiedAt;
198    }
199
200    /**
201     * Gets the time that this version of the file was deleted.
202     *
203     * @return the time that this version of the file was deleted.
204     */
205    public Date getTrashedAt() {
206        return this.trashedAt;
207    }
208
209    /**
210     * Gets information about the user who trashed this version of the file.
211     *
212     * @return info about the user who trashed this version of the file.
213     */
214    public BoxUser.Info getTrashedBy() {
215        return this.trashedBy;
216    }
217
218    /**
219     * Gets information about the user who last modified this version of the file.
220     *
221     * @return info about the user who last modified this version of the file.
222     */
223    public BoxUser.Info getModifiedBy() {
224        return this.modifiedBy;
225    }
226
227    /**
228     * Gets the time that this version of the file was restored.
229     *
230     * @return the time that this version of the file was restored.
231     */
232    public Date getRestoredAt() {
233        return this.restoredAt;
234    }
235
236    /**
237     * Gets information about the user who restored this version of the file.
238     *
239     * @return info about the user who restored this version of the file.
240     */
241    public BoxUser.Info getRestoredBy() {
242        return this.restoredBy;
243    }
244
245    /**
246     * Gets the time that this version of the file was purged.
247     *
248     * @return the time that this version of the file was purged.
249     */
250    public Date getPurgedAt() {
251        return this.purgedAt;
252    }
253
254    /**
255     * Returns version number.
256     *
257     * @return version number
258     */
259    public Long getVersionNumber() {
260        return versionNumber;
261    }
262
263    /**
264     * Deletes this version of the file.
265     */
266    public void delete() {
267        URL url = VERSION_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.fileID, this.getID());
268        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE");
269        BoxAPIResponse response = request.send();
270        response.disconnect();
271    }
272
273    /**
274     * Downloads this version of the file to a given OutputStream.
275     *
276     * @param output the stream to where the file will be written.
277     */
278    public void download(OutputStream output) {
279        this.download(output, null);
280    }
281
282    /**
283     * Downloads this version of the file to a given OutputStream while reporting the progress to a ProgressListener.
284     *
285     * @param output   the stream to where the file will be written.
286     * @param listener a listener for monitoring the download's progress.
287     */
288    public void download(OutputStream output, ProgressListener listener) {
289        URL url = CONTENT_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.fileID, this.getID());
290        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
291        BoxAPIResponse response = request.send();
292        InputStream input = response.getBody(listener);
293
294        byte[] buffer = new byte[BUFFER_SIZE];
295        try {
296            int n = input.read(buffer);
297            while (n != -1) {
298                output.write(buffer, 0, n);
299                n = input.read(buffer);
300            }
301        } catch (IOException e) {
302            throw new BoxAPIException("Couldn't connect to the Box API due to a network error.", e);
303        }
304
305        response.disconnect();
306    }
307
308    /**
309     * Promotes this version of the file to be the latest version.
310     */
311    public void promote() {
312        URL url = VERSION_URL_TEMPLATE.buildAlpha(this.getAPI().getBaseURL(), this.fileID, "current");
313
314        JsonObject jsonObject = new JsonObject();
315        jsonObject.add("type", "file_version");
316        jsonObject.add("id", this.getID());
317
318        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST");
319        request.setBody(jsonObject.toString());
320        BoxJSONResponse response = (BoxJSONResponse) request.send();
321        this.parseJSON(Json.parse(response.getJSON()).asObject());
322    }
323}