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    private static final URLTemplate CONTENT_URL_TEMPLATE = new URLTemplate("files/%s/content?version=%s");
019    private static final URLTemplate VERSION_URL_TEMPLATE = new URLTemplate("files/%s/versions/%s");
020    private static final int BUFFER_SIZE = 8192;
021
022    private String fileID;
023
024    private String versionID;
025    private String sha1;
026    private String name;
027    private long size;
028    private Date createdAt;
029    private Date modifiedAt;
030    private BoxUser.Info modifiedBy;
031    private Date trashedAt;
032
033    /**
034     * Constructs a BoxFileVersion from a JSON string.
035     * @param  api    the API connection to be used by the file.
036     * @param  json   the JSON encoded file version.
037     * @param  fileID the ID of the file.
038     */
039    public BoxFileVersion(BoxAPIConnection api, String json, String fileID) {
040        this(api, JsonObject.readFrom(json), fileID);
041    }
042
043    BoxFileVersion(BoxAPIConnection api, JsonObject jsonObject, String fileID) {
044        super(api, jsonObject.get("id").asString());
045
046        this.fileID = fileID;
047        this.parseJSON(jsonObject);
048    }
049
050    /**
051     * Method used to update fields with values received from API.
052     * @param jsonObject JSON-encoded info about File Version object.
053     */
054    private void parseJSON(JsonObject jsonObject) {
055        for (JsonObject.Member member : jsonObject) {
056            JsonValue value = member.getValue();
057            if (value.isNull()) {
058                continue;
059            }
060
061            try {
062                String memberName = member.getName();
063                if (memberName.equals("id")) {
064                    this.versionID = value.asString();
065                } else if (memberName.equals("sha1")) {
066                    this.sha1 = value.asString();
067                } else if (memberName.equals("name")) {
068                    this.name = value.asString();
069                } else if (memberName.equals("size")) {
070                    this.size = Double.valueOf(value.toString()).longValue();
071                } else if (memberName.equals("created_at")) {
072                    this.createdAt = BoxDateFormat.parse(value.asString());
073                } else if (memberName.equals("modified_at")) {
074                    this.modifiedAt = BoxDateFormat.parse(value.asString());
075                } else if (memberName.equals("trashed_at")) {
076                    this.trashedAt = BoxDateFormat.parse(value.asString());
077                } else if (memberName.equals("modified_by")) {
078                    JsonObject userJSON = value.asObject();
079                    String userID = userJSON.get("id").asString();
080                    BoxUser user = new BoxUser(getAPI(), userID);
081                    this.modifiedBy = user.new Info(userJSON);
082                }
083            } catch (ParseException e) {
084                assert false : "A ParseException indicates a bug in the SDK.";
085            }
086        }
087    }
088
089    /**
090     * Used if no or wrong file id was set with constructor.
091     * @param fileID the file id this file version belongs to.
092     */
093    public void setFileID(String fileID) {
094        this.fileID = fileID;
095    }
096
097    /**
098     * @return the file id this file version belongs to.
099     */
100    public String getFileID() {
101        return this.fileID;
102    }
103
104    /**
105     * Gets the version ID of this version of the file.
106     * @return the version ID of this version of the file.
107     */
108    public String getVersionID() {
109        return this.versionID;
110    }
111
112    /**
113     * Gets the SHA1 hash of this version of the file.
114     * @return the SHA1 hash of this version of the file.
115     */
116    public String getSha1() {
117        return this.sha1;
118    }
119
120    /**
121     * Gets the name of this version of the file.
122     * @return the name of this version of the file.
123     */
124    public String getName() {
125        return this.name;
126    }
127
128    /**
129     * Gets the size of this version of the file.
130     * @return the size of this version of the file.
131     */
132    public long getSize() {
133        return this.size;
134    }
135
136    /**
137     * Gets the time that this version of the file was created.
138     * @return the time that this version of the file was created.
139     */
140    public Date getCreatedAt() {
141        return this.createdAt;
142    }
143
144    /**
145     * Gets the time that this version of the file was modified.
146     * @return the time that this version of the file was modified.
147     */
148    public Date getModifiedAt() {
149        return this.modifiedAt;
150    }
151
152    /**
153     * Gets the time that this version of the file was deleted.
154     * @return the time that this version of the file was deleted.
155     */
156    public Date getTrashedAt() {
157        return this.trashedAt;
158    }
159
160    /**
161     * Gets information about the user who last modified this version of the file.
162     * @return info about the user who last modified this version of the file.
163     */
164    public BoxUser.Info getModifiedBy() {
165        return this.modifiedBy;
166    }
167
168    /**
169     * Deletes this version of the file.
170     */
171    public void delete() {
172        URL url = VERSION_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.fileID, this.getID());
173        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE");
174        BoxAPIResponse response = request.send();
175        response.disconnect();
176    }
177
178    /**
179     * Downloads this version of the file to a given OutputStream.
180     * @param output the stream to where the file will be written.
181     */
182    public void download(OutputStream output) {
183        this.download(output, null);
184    }
185
186    /**
187     * Downloads this version of the file to a given OutputStream while reporting the progress to a ProgressListener.
188     * @param output   the stream to where the file will be written.
189     * @param listener a listener for monitoring the download's progress.
190     */
191    public void download(OutputStream output, ProgressListener listener) {
192        URL url = CONTENT_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.fileID, this.getID());
193        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
194        BoxAPIResponse response = request.send();
195        InputStream input = response.getBody(listener);
196
197        long totalRead = 0;
198        byte[] buffer = new byte[BUFFER_SIZE];
199        try {
200            int n = input.read(buffer);
201            totalRead += n;
202            while (n != -1) {
203                output.write(buffer, 0, n);
204                n = input.read(buffer);
205                totalRead += n;
206            }
207        } catch (IOException e) {
208            throw new BoxAPIException("Couldn't connect to the Box API due to a network error.", e);
209        }
210
211        response.disconnect();
212    }
213
214    /**
215     * Promotes this version of the file to be the latest version.
216     */
217    public void promote() {
218        URL url = VERSION_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.fileID, "current");
219
220        JsonObject jsonObject = new JsonObject();
221        jsonObject.add("type", "file_version");
222        jsonObject.add("id", this.getID());
223
224        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST");
225        request.setBody(jsonObject.toString());
226        BoxJSONResponse response = (BoxJSONResponse) request.send();
227        this.parseJSON(JsonObject.readFrom(response.getJSON()));
228    }
229}