001package com.box.sdk;
002
003import java.net.URL;
004import java.util.Iterator;
005
006import com.eclipsesource.json.JsonArray;
007import com.eclipsesource.json.JsonObject;
008import com.eclipsesource.json.JsonValue;
009
010/**
011 * Collections contain information about the items contained inside of them, including files and folders. The only
012 * collection available currently is a “Favorites” collection.
013 *
014 * <p>Unless otherwise noted, the methods in this class can throw an unchecked {@link BoxAPIException} (unchecked
015 * meaning that the compiler won't force you to handle it) if an error occurs. If you wish to implement custom error
016 * handling for errors related to the Box REST API, you should capture this exception explicitly.</p>
017 */
018@BoxResourceType("collection")
019public class BoxCollection extends BoxResource implements Iterable<BoxItem.Info> {
020
021    private static final URLTemplate GET_COLLECTIONS_URL_TEMPLATE = new URLTemplate("collections/");
022    private static final URLTemplate GET_COLLECTION_ITEMS_URL = new URLTemplate("collections/%s/items/");
023
024    /**
025     * Constructs a BoxCollection for a collection with a given ID.
026     * @param   api the API connection to be used by the collection.
027     * @param   id  the ID of the collection.
028     */
029    public BoxCollection(BoxAPIConnection api, String id) {
030        super(api, id);
031    }
032
033    /**
034     * Gets an iterable of all the collections for the given user.
035     * @param  api the API connection to be used when retrieving the collections.
036     * @return     an iterable containing info about all the collections.
037     */
038    public static Iterable<BoxCollection.Info> getAllCollections(final BoxAPIConnection api) {
039        return new Iterable<BoxCollection.Info>() {
040            public Iterator<BoxCollection.Info> iterator() {
041                URL url = GET_COLLECTIONS_URL_TEMPLATE.build(api.getBaseURL());
042                return new BoxCollectionIterator(api, url);
043            }
044        };
045    }
046
047    /**
048     * Returns an iterable containing the items in this collection. Iterating over the iterable returned by this method
049     * is equivalent to iterating over this BoxCollection directly.
050     * @return an iterable containing the items in this collection.
051     */
052    public Iterable<BoxItem.Info> getItems() {
053        return this;
054    }
055
056    /**
057     * Returns an iterable containing the items in this collection and specifies which attributes to include in the
058     * response.
059     * @param   fields  the fields to retrieve.
060     * @return          an iterable containing the items in this collection.
061     */
062    public Iterable<BoxItem.Info> getItems(final String... fields) {
063        return new Iterable<BoxItem.Info>() {
064            @Override
065            public Iterator<BoxItem.Info> iterator() {
066                String queryString = new QueryStringBuilder().appendParam("fields", fields).toString();
067                URL url = GET_COLLECTION_ITEMS_URL.buildWithQuery(getAPI().getBaseURL(), queryString, getID());
068                return new BoxItemIterator(getAPI(), url);
069            }
070        };
071    }
072
073    /**
074     * Retrieves a specific range of items in this collection.
075     * @param   offset  the index of the first item to retrieve.
076     * @param   limit   the maximum number of items to retrieve after the offset.
077     * @param   fields  the fields to retrieve.
078     * @return          a partial collection containing the specified range of items.
079     */
080    public PartialCollection<BoxItem.Info> getItemsRange(long offset, long limit, String... fields) {
081        QueryStringBuilder builder = new QueryStringBuilder()
082                .appendParam("offset", offset)
083                .appendParam("limit", limit);
084
085        if (fields.length > 0) {
086            builder.appendParam("fields", fields).toString();
087        }
088
089        URL url = GET_COLLECTION_ITEMS_URL.buildWithQuery(getAPI().getBaseURL(), builder.toString(), getID());
090        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
091        BoxJSONResponse response = (BoxJSONResponse) request.send();
092        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
093
094        String totalCountString = responseJSON.get("total_count").toString();
095        long fullSize = Double.valueOf(totalCountString).longValue();
096        PartialCollection<BoxItem.Info> items = new PartialCollection<BoxItem.Info>(offset, limit, fullSize);
097        JsonArray entries = responseJSON.get("entries").asArray();
098        for (JsonValue entry : entries) {
099            BoxItem.Info entryInfo = (BoxItem.Info) BoxResource.parseInfo(this.getAPI(), entry.asObject());
100            if (entryInfo != null) {
101                items.add(entryInfo);
102            }
103        }
104        return items;
105    }
106
107    /**
108     * Returns an iterator over the items in this collection.
109     * @return an iterator over the items in this collection.
110     */
111    @Override
112    public Iterator<BoxItem.Info> iterator() {
113        URL url = GET_COLLECTION_ITEMS_URL.build(this.getAPI().getBaseURL(), BoxCollection.this.getID());
114        return new BoxItemIterator(BoxCollection.this.getAPI(), url);
115    }
116
117    /**
118     * Contains information about a BoxCollection.
119     */
120    public class Info extends BoxResource.Info {
121        private String collectionType;
122        private String name;
123
124        /**
125         * Constructs an empty Info object.
126         */
127        public Info() {
128            super();
129        }
130
131        /**
132         * Constructs an Info object by parsing information from a JSON string.
133         * @param json the JSON string to parse.
134         */
135        public Info(String json) {
136            super(json);
137        }
138
139        /**
140         * Constructs an Info object using an already parsed JSON object.
141         * @param jsonObject the parsed JSON object.
142         */
143        Info(JsonObject jsonObject) {
144            super(jsonObject);
145        }
146
147        /**
148         * Gets the type of the collection.
149         * @return the type of the collection.
150         */
151        public String getCollectionType() {
152            return this.collectionType;
153        }
154
155        /**
156         * Gets the name of the collection.
157         * @return the name of the collection.
158         */
159        public String getName() {
160            return this.name;
161        }
162
163        @Override
164        public BoxCollection getResource() {
165            return BoxCollection.this;
166        }
167
168        @Override
169        protected void parseJSONMember(JsonObject.Member member) {
170            super.parseJSONMember(member);
171
172            String memberName = member.getName();
173            JsonValue value = member.getValue();
174            if (memberName.equals("collection_type")) {
175                this.collectionType = value.asString();
176            } else if (memberName.equals("name")) {
177                this.name = value.asString();
178            }
179        }
180    }
181}