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