001package com.box.sdk; 002 003import com.eclipsesource.json.JsonArray; 004import com.eclipsesource.json.JsonObject; 005import com.eclipsesource.json.JsonValue; 006import java.net.MalformedURLException; 007import java.net.URL; 008import java.util.Date; 009import java.util.Iterator; 010import java.util.LinkedHashSet; 011import java.util.Set; 012 013/** 014 * A log of events that were retrieved from the events endpoint. 015 * 016 * <p>An EventLog cannot be instantiated directly. Instead, use one of the static methods to retrieve a log of events. 017 * Unlike the {@link EventStream} class, EventLog doesn't support retrieving events in real-time. 018 * </p> 019 */ 020public class EventLog implements Iterable<BoxEvent> { 021 022 private static final int ENTERPRISE_LIMIT = 500; 023 /** 024 * Enterprise Event URL Template. 025 */ 026 public static final URLTemplate ENTERPRISE_EVENT_URL_TEMPLATE = new URLTemplate("events?stream_type=admin_logs&" 027 + "limit=" + ENTERPRISE_LIMIT); 028 private final int chunkSize; 029 private final int limit; 030 private final String nextStreamPosition; 031 private final String streamPosition; 032 private final Set<BoxEvent> set; 033 034 private Date startDate; 035 private Date endDate; 036 037 EventLog(BoxAPIConnection api, JsonObject json, String streamPosition, int limit) { 038 this.streamPosition = streamPosition; 039 this.limit = limit; 040 this.nextStreamPosition = json.get("next_stream_position").asString(); 041 this.chunkSize = json.get("chunk_size").asInt(); 042 043 this.set = new LinkedHashSet<BoxEvent>(this.chunkSize); 044 JsonArray entries = json.get("entries").asArray(); 045 for (JsonValue entry : entries) { 046 this.set.add(new BoxEvent(api, entry.asObject())); 047 } 048 } 049 050 /** 051 * Gets all the enterprise events that occurred within a specified date range, starting from a given position 052 * within the event stream. 053 * 054 * @param api the API connection to use. 055 * @param position the starting position of the event stream. 056 * @param after the lower bound on the timestamp of the events returned. 057 * @param before the upper bound on the timestamp of the events returned. 058 * @param types an optional list of event types to filter by. 059 * @return a log of all the events that met the given criteria. 060 */ 061 public static EventLog getEnterpriseEvents(BoxAPIConnection api, String position, Date after, Date before, 062 BoxEvent.Type... types) { 063 return getEnterpriseEvents(api, position, after, before, ENTERPRISE_LIMIT, types); 064 } 065 066 /** 067 * Gets all the enterprise events that occurred within a specified date range. 068 * 069 * @param api the API connection to use. 070 * @param after the lower bound on the timestamp of the events returned. 071 * @param before the upper bound on the timestamp of the events returned. 072 * @param types an optional list of event types to filter by. 073 * @return a log of all the events that met the given criteria. 074 */ 075 public static EventLog getEnterpriseEvents(BoxAPIConnection api, Date after, Date before, BoxEvent.Type... types) { 076 return getEnterpriseEvents(api, null, after, before, ENTERPRISE_LIMIT, types); 077 } 078 079 /** 080 * Gets all the enterprise events that occurred within a specified date range, starting from a given position 081 * within the event stream. 082 * 083 * @param api the API connection to use. 084 * @param position the starting position of the event stream. 085 * @param after the lower bound on the timestamp of the events returned. 086 * @param before the upper bound on the timestamp of the events returned. 087 * @param limit the number of entries to be returned in the response. 088 * @param types an optional list of event types to filter by. 089 * @return a log of all the events that met the given criteria. 090 */ 091 public static EventLog getEnterpriseEvents(BoxAPIConnection api, String position, Date after, Date before, 092 int limit, BoxEvent.Type... types) { 093 094 URL url = ENTERPRISE_EVENT_URL_TEMPLATE.build(api.getBaseURL()); 095 096 if (position != null || types.length > 0 || after != null 097 || before != null || limit != ENTERPRISE_LIMIT) { 098 QueryStringBuilder queryBuilder = new QueryStringBuilder(url.getQuery()); 099 100 if (after != null) { 101 queryBuilder.appendParam("created_after", 102 BoxDateFormat.format(after)); 103 } 104 105 if (before != null) { 106 queryBuilder.appendParam("created_before", 107 BoxDateFormat.format(before)); 108 } 109 110 if (position != null) { 111 queryBuilder.appendParam("stream_position", position); 112 } 113 114 if (limit != ENTERPRISE_LIMIT) { 115 queryBuilder.appendParam("limit", limit); 116 } 117 118 if (types.length > 0) { 119 StringBuilder filterBuilder = new StringBuilder(); 120 for (BoxEvent.Type filterType : types) { 121 filterBuilder.append(filterType.name()); 122 filterBuilder.append(','); 123 } 124 filterBuilder.deleteCharAt(filterBuilder.length() - 1); 125 queryBuilder.appendParam("event_type", filterBuilder.toString()); 126 } 127 128 try { 129 url = queryBuilder.addToURL(url); 130 } catch (MalformedURLException e) { 131 throw new BoxAPIException("Couldn't append a query string to the provided URL."); 132 } 133 } 134 135 BoxAPIRequest request = new BoxAPIRequest(api, url, "GET"); 136 BoxJSONResponse response = (BoxJSONResponse) request.send(); 137 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 138 EventLog log = new EventLog(api, responseJSON, position, limit); 139 log.setStartDate(after); 140 log.setEndDate(before); 141 return log; 142 } 143 144 /** 145 * Returns an iterator over the events in this log. 146 * 147 * @return an iterator over the events in this log. 148 */ 149 @Override 150 public Iterator<BoxEvent> iterator() { 151 return this.set.iterator(); 152 } 153 154 /** 155 * Gets the date of the earliest event in this log. 156 * 157 * <p>The value returned by this method corresponds to the <code>created_after</code> URL parameter that was used 158 * when retrieving the events in this EventLog.</p> 159 * 160 * @return the date of the earliest event in this log. 161 */ 162 public Date getStartDate() { 163 return this.startDate; 164 } 165 166 void setStartDate(Date startDate) { 167 this.startDate = startDate; 168 } 169 170 /** 171 * Gets the date of the latest event in this log. 172 * 173 * <p>The value returned by this method corresponds to the <code>created_before</code> URL parameter that was used 174 * when retrieving the events in this EventLog.</p> 175 * 176 * @return the date of the latest event in this log. 177 */ 178 public Date getEndDate() { 179 return this.endDate; 180 } 181 182 void setEndDate(Date endDate) { 183 this.endDate = endDate; 184 } 185 186 /** 187 * Gets the maximum number of events that this event log could contain given its start date, end date, and stream 188 * position. 189 * 190 * <p>The value returned by this method corresponds to the <code>limit</code> URL parameter that was used when 191 * retrieving the events in this EventLog.</p> 192 * 193 * @return the maximum number of events. 194 */ 195 public int getLimit() { 196 return this.limit; 197 } 198 199 /** 200 * Gets the starting position of the events in this log within the event stream. 201 * 202 * <p>The value returned by this method corresponds to the <code>stream_position</code> URL parameter that was used 203 * when retrieving the events in this EventLog.</p> 204 * 205 * @return the starting position within the event stream. 206 */ 207 public String getStreamPosition() { 208 return this.streamPosition; 209 } 210 211 /** 212 * Gets the next position within the event stream for retrieving subsequent events. 213 * 214 * <p>The value returned by this method corresponds to the <code>next_stream_position</code> field returned by the 215 * API's events endpoint.</p> 216 * 217 * @return the next position within the event stream. 218 */ 219 public String getNextStreamPosition() { 220 return this.nextStreamPosition; 221 } 222 223 /** 224 * Gets the number of events in this log, including duplicate events. 225 * 226 * <p>The chunk size may not be representative of the number of events returned by this EventLog's iterator because 227 * the iterator will automatically ignore duplicate events.</p> 228 * 229 * <p>The value returned by this method corresponds to the <code>chunk_size</code> field returned by the API's 230 * events endpoint.</p> 231 * 232 * @return the number of events, including duplicates. 233 */ 234 public int getChunkSize() { 235 return this.chunkSize; 236 } 237 238 /** 239 * Gets the number of events in this list, excluding duplicate events. 240 * 241 * <p>The size is guaranteed to be representative of the number of events returned by this EventLog's iterator.</p> 242 * 243 * @return the number of events, excluding duplicates. 244 */ 245 public int getSize() { 246 return this.set.size(); 247 } 248}