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    /**
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     * @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     * @param  api the API connection to be used when retrieving the collections.
042     * @return     an iterable containing info about all the collections.
043     */
044    public static Iterable<BoxCollection.Info> getAllCollections(final BoxAPIConnection api) {
045        return new Iterable<BoxCollection.Info>() {
046            public Iterator<BoxCollection.Info> iterator() {
047                URL url = GET_COLLECTIONS_URL_TEMPLATE.build(api.getBaseURL());
048                return new BoxCollectionIterator(api, url);
049            }
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     * @return an iterable containing the items in this collection.
057     */
058    public Iterable<BoxItem.Info> getItems() {
059        return this;
060    }
061
062    /**
063     * Returns an iterable containing the items in this collection and specifies which attributes to include in the
064     * response.
065     * @param   fields  the fields to retrieve.
066     * @return          an iterable containing the items in this collection.
067     */
068    public Iterable<BoxItem.Info> getItems(final String... fields) {
069        return new Iterable<BoxItem.Info>() {
070            @Override
071            public Iterator<BoxItem.Info> iterator() {
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    /**
080     * Retrieves a specific range of items in this collection.
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).toString();
093        }
094
095        URL url = GET_COLLECTION_ITEMS_URL.buildWithQuery(getAPI().getBaseURL(), builder.toString(), getID());
096        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
097        BoxJSONResponse response = (BoxJSONResponse) request.send();
098        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
099
100        String totalCountString = responseJSON.get("total_count").toString();
101        long fullSize = Double.valueOf(totalCountString).longValue();
102        PartialCollection<BoxItem.Info> items = new PartialCollection<BoxItem.Info>(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     * Returns an iterator over the items in this collection.
115     * @return an iterator over the items in this collection.
116     */
117    @Override
118    public Iterator<BoxItem.Info> iterator() {
119        URL url = GET_COLLECTION_ITEMS_URL.build(this.getAPI().getBaseURL(), BoxCollection.this.getID());
120        return new BoxItemIterator(BoxCollection.this.getAPI(), url);
121    }
122
123    /**
124     * Contains information about a BoxCollection.
125     */
126    public class Info extends BoxResource.Info {
127        private String collectionType;
128        private String name;
129
130        /**
131         * Constructs an empty Info object.
132         */
133        public Info() {
134            super();
135        }
136
137        /**
138         * Constructs an Info object by parsing information from a JSON string.
139         * @param json the JSON string to parse.
140         */
141        public Info(String json) {
142            super(json);
143        }
144
145        /**
146         * Constructs an Info object using an already parsed JSON object.
147         * @param jsonObject the parsed JSON object.
148         */
149        Info(JsonObject jsonObject) {
150            super(jsonObject);
151        }
152
153        /**
154         * Gets the type of the collection.
155         * @return the type of the collection.
156         */
157        public String getCollectionType() {
158            return this.collectionType;
159        }
160
161        /**
162         * Gets the name of the collection.
163         * @return the name of the collection.
164         */
165        public String getName() {
166            return this.name;
167        }
168
169        @Override
170        public BoxCollection getResource() {
171            return BoxCollection.this;
172        }
173
174        @Override
175        protected void parseJSONMember(JsonObject.Member member) {
176            super.parseJSONMember(member);
177
178            String memberName = member.getName();
179            JsonValue value = member.getValue();
180            if (memberName.equals("collection_type")) {
181                this.collectionType = value.asString();
182            } else if (memberName.equals("name")) {
183                this.name = value.asString();
184            }
185        }
186    }
187}