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