/*
* Copyright 2007 Yusuke Yamamoto
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package twitter4j.internal.json;
import twitter4j.*;
import twitter4j.conf.Configuration;
import twitter4j.internal.http.HttpResponse;
import twitter4j.internal.org.json.JSONArray;
import twitter4j.internal.org.json.JSONException;
import twitter4j.internal.org.json.JSONObject;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import static twitter4j.internal.json.z_T4JInternalParseUtil.*;
/**
* A data class representing search API response
*
* @author Yusuke Yamamoto - yusuke at mac.com
*/
/*package*/ final class QueryResultJSONImpl extends TwitterResponseImpl implements QueryResult, java.io.Serializable {
private static final long serialVersionUID = -6781654399437121238L;
private long sinceId;
private long maxId;
private String refreshUrl;
private int count;
private double completedIn;
private String query;
private List<Status> tweets;
private String nextResults;
// private static factory method to instantiate Query class with "next_page"
// http://jira.twitter4j.org/browse/TFJ-549
static Method queryFactoryMethod;
static {
Method[] methods = Query.class.getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equals("createWithNextPageQuery")) {
queryFactoryMethod = method;
queryFactoryMethod.setAccessible(true);
break;
}
}
if (queryFactoryMethod == null) {
throw new ExceptionInInitializerError(new NoSuchMethodException("twitter4j.Query.createWithNextPageQuery(java.lang.String)"));
}
}
/*package*/ QueryResultJSONImpl(HttpResponse res, Configuration conf) throws TwitterException {
super(res);
JSONObject json = res.asJSONObject();
try {
JSONObject searchMetaData = json.getJSONObject("search_metadata");
completedIn = getDouble("completed_in", searchMetaData);
count = getInt("count", searchMetaData);
maxId = getLong("max_id", searchMetaData);
nextResults = searchMetaData.has("next_results") ? searchMetaData.getString("next_results") : null;
query = getURLDecodedString("query", searchMetaData);
refreshUrl = getUnescapedString("refresh_url", searchMetaData);
sinceId = getLong("since_id", searchMetaData);
JSONArray array = json.getJSONArray("statuses");
tweets = new ArrayList<Status>(array.length());
if (conf.isJSONStoreEnabled()) {
DataObjectFactoryUtil.clearThreadLocalMap();
}
for (int i = 0; i < array.length(); i++) {
JSONObject tweet = array.getJSONObject(i);
tweets.add(new StatusJSONImpl(tweet, conf));
}
} catch (JSONException jsone) {
throw new TwitterException(jsone.getMessage() + ":" + json.toString(), jsone);
}
}
/*package*/ QueryResultJSONImpl(Query query) {
super();
sinceId = query.getSinceId();
count = query.getCount();
tweets = new ArrayList<Status>(0);
}
/**
* {@inheritDoc}
*/
@Override
public long getSinceId() {
return sinceId;
}
/**
* {@inheritDoc}
*/
@Override
public long getMaxId() {
return maxId;
}
/**
* {@inheritDoc}
*/
@Override
public String getRefreshUrl() {
return getRefreshURL();
}
@Override
public String getRefreshURL() {
return refreshUrl;
}
/**
* {@inheritDoc}
*/
@Override
public int getCount() {
return count;
}
/**
* {@inheritDoc}
*/
@Override
public double getCompletedIn() {
return completedIn;
}
/**
* {@inheritDoc}
*/
@Override
public String getQuery() {
return query;
}
/**
* {@inheritDoc}
*/
@Override
public List<Status> getTweets() {
return tweets;
}
/**
* {@inheritDoc}
*/
@Override
public Query nextQuery() {
if (nextResults == null) {
return null;
}
try {
return (Query) queryFactoryMethod.invoke(null, new String[]{nextResults});
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasNext() {
return nextResults != null;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
QueryResult that = (QueryResult) o;
if (Double.compare(that.getCompletedIn(), completedIn) != 0)
return false;
if (maxId != that.getMaxId()) return false;
if (count != that.getCount()) return false;
if (sinceId != that.getSinceId()) return false;
if (!query.equals(that.getQuery())) return false;
if (refreshUrl != null ? !refreshUrl.equals(that.getRefreshUrl()) : that.getRefreshUrl() != null)
return false;
if (tweets != null ? !tweets.equals(that.getTweets()) : that.getTweets() != null)
return false;
return true;
}
@Override
public int hashCode() {
int result;
long temp;
result = (int) (sinceId ^ (sinceId >>> 32));
result = 31 * result + (int) (maxId ^ (maxId >>> 32));
result = 31 * result + (refreshUrl != null ? refreshUrl.hashCode() : 0);
result = 31 * result + count;
temp = completedIn != +0.0d ? Double.doubleToLongBits(completedIn) : 0L;
result = 31 * result + (int) (temp ^ (temp >>> 32));
result = 31 * result + query.hashCode();
result = 31 * result + (tweets != null ? tweets.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "QueryResultJSONImpl{" +
"sinceId=" + sinceId +
", maxId=" + maxId +
", refreshUrl='" + refreshUrl + '\'' +
", count=" + count +
", completedIn=" + completedIn +
", query='" + query + '\'' +
", tweets=" + tweets +
'}';
}
}