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