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