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