1.9.30 sync.
[gae.git] / java / src / main / com / google / appengine / api / log / LogQueryResult.java
blob773a6d93b712ade8eae6afafe7f702b2249905e4
1 // Copyright 2011 Google Inc. All Rights Reserved.
3 package com.google.appengine.api.log;
5 import static com.google.common.io.BaseEncoding.base64;
7 import com.google.apphosting.api.logservice.LogServicePb.LogOffset;
8 import com.google.apphosting.api.logservice.LogServicePb.LogReadResponse;
9 import com.google.apphosting.api.logservice.LogServicePb.RequestLog;
10 import com.google.common.base.CharMatcher;
11 import com.google.common.collect.AbstractIterator;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.Iterator;
16 import java.util.List;
18 /**
19 * An object that is the result of performing a LogService.fetch() operation.
20 * LogQueryResults contain the logs from the user's query. Users of this service
21 * should use the {@link LogQueryResult#iterator} provided by this class to
22 * retrieve their results.
25 public final class LogQueryResult implements Iterable<RequestLogs> {
26 private final List<RequestLogs> logs;
27 private final String cursor;
28 private final LogQuery query;
30 protected LogQueryResult(LogReadResponse response, LogQuery originalQuery) {
31 logs = new ArrayList<RequestLogs>();
32 for (RequestLog log : response.logs()) {
33 String offset = base64().encode(log.getOffset().toByteArray());
34 logs.add(new RequestLogs(log, offset));
37 if (response.hasOffset()) {
38 cursor = base64().encode(response.getOffset().toByteArray());
39 } else {
40 cursor = null;
43 query = originalQuery.clone();
46 /**
47 * Returns a LogOffset parsed from the submitted String, which is assumed to
48 * be a Base64-encoded offset produced by this class.
50 * @return A String to parse as a Base64-encoded LogOffset protocol buffer.
52 protected static LogOffset parseOffset(String offset) {
53 LogOffset logOffset = new LogOffset();
54 try {
55 boolean parsed =
56 logOffset.parseFrom(base64().decode(CharMatcher.WHITESPACE.removeFrom(offset)));
57 if (!parsed || !logOffset.isInitialized()) {
58 throw new IllegalArgumentException();
60 } catch (IllegalArgumentException e) {
61 throw new IllegalArgumentException("Can not parse provided offset.");
63 return logOffset;
66 /**
67 * Returns the list of logs internally kept by this class. The main user of
68 * this method is iterator, who needs it to give the user logs as needed.
70 * @return A List of RequestLogs acquired from a fetch() request.
72 private List<RequestLogs> getLogs() {
73 return Collections.unmodifiableList(logs);
76 /**
77 * Returns the String version of the database cursor, which can be used to
78 * tell subsequent fetch() requests where to start scanning from. The main
79 * user of this method is iterator, who uses it to ensure that users get all
80 * the logs they requested.
82 * @return A String representing the next location in the database to read
83 * from.
85 private String getCursor() {
86 return cursor;
89 /**
90 * Returns an Iterator that will yield all of the logs the user has requested.
91 * If the user has asked for more logs than a single request can accommodate
92 * (which is LogService.MAX_ITEMS_PER_FETCH), then this iterator grabs
93 * the first batch and returns them until they are exhausted. Once they are
94 * exhausted, a fetch() call is made to get more logs and the process is
95 * repeated until either all of the logs have been read or the user has
96 * stopped asking for more logs.
98 * @return An iterator that provides RequestLogs to the caller.
100 @Override
101 public Iterator<RequestLogs> iterator() {
102 return new AbstractIterator<RequestLogs>() {
103 List<RequestLogs> iterLogs = logs;
104 String iterCursor = cursor;
105 int index = 0;
106 int lengthLogs = iterLogs.size();
108 @Override
109 protected RequestLogs computeNext() {
110 while (index >= lengthLogs) {
111 if (iterCursor == null) {
112 return endOfData();
115 query.offset(iterCursor);
117 LogQueryResult nextResults = new LogServiceImpl().fetch(query);
118 iterLogs = nextResults.getLogs();
119 iterCursor = nextResults.getCursor();
120 lengthLogs = iterLogs.size();
121 index = 0;
124 return iterLogs.get(index++);