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