/* * 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.RateLimitStatus; import twitter4j.TwitterException; import twitter4j.conf.Configuration; import twitter4j.internal.http.HttpResponse; import twitter4j.internal.org.json.JSONException; import twitter4j.internal.org.json.JSONObject; import java.util.*; import static twitter4j.internal.json.z_T4JInternalParseUtil.getDate; import static twitter4j.internal.json.z_T4JInternalParseUtil.getInt; /** * A data class representing Twitter REST API's rate limit status * * @author Yusuke Yamamoto - yusuke at mac.com * @see <a href="https://dev.twitter.com/docs/rate-limiting">Rate Limiting | Twitter Developers</a> */ /*package*/ final class RateLimitStatusJSONImpl implements RateLimitStatus, java.io.Serializable { private static final long serialVersionUID = 1625565652687304084L; private int remaining; private int limit; private int resetTimeInSeconds; private int secondsUntilReset; static Map<String,RateLimitStatus> createRateLimitStatuses(HttpResponse res, Configuration conf) throws TwitterException { JSONObject json = res.asJSONObject(); Map<String, RateLimitStatus> map = createRateLimitStatuses(json); if (conf.isJSONStoreEnabled()) { DataObjectFactoryUtil.clearThreadLocalMap(); DataObjectFactoryUtil.registerJSONObject(map, json); } return map; } static Map<String,RateLimitStatus> createRateLimitStatuses(JSONObject json) throws TwitterException { Map<String, RateLimitStatus> map = new HashMap<String, RateLimitStatus>(); try { JSONObject resources = json.getJSONObject("resources"); Iterator resourceKeys = resources.keys(); while (resourceKeys.hasNext()) { JSONObject resource = resources.getJSONObject((String) resourceKeys.next()); Iterator endpointKeys = resource.keys(); while (endpointKeys.hasNext()) { String endpoint = (String) endpointKeys.next(); JSONObject rateLimitStatusJSON = resource.getJSONObject(endpoint); RateLimitStatus rateLimitStatus = new RateLimitStatusJSONImpl(rateLimitStatusJSON); map.put(endpoint, rateLimitStatus); } } return Collections.unmodifiableMap(map); } catch (JSONException jsone) { throw new TwitterException(jsone); } } private RateLimitStatusJSONImpl(int limit, int remaining, int resetTimeInSeconds) { this.limit = limit; this.remaining = remaining; this.resetTimeInSeconds = resetTimeInSeconds; this.secondsUntilReset = (int) ((resetTimeInSeconds * 1000L - System.currentTimeMillis()) / 1000); } RateLimitStatusJSONImpl(JSONObject json) throws TwitterException { init(json); } void init(JSONObject json) throws TwitterException { this.limit = getInt("limit", json); this.remaining = getInt("remaining", json); this.resetTimeInSeconds = getInt("reset", json); this.secondsUntilReset = (int) ((resetTimeInSeconds * 1000L - System.currentTimeMillis()) / 1000); } static RateLimitStatus createFromResponseHeader(HttpResponse res) { if (null == res) { return null; } int remainingHits;//"X-Rate-Limit-Remaining" int limit;//"X-Rate-Limit-Limit" int resetTimeInSeconds;//not included in the response header. Need to be calculated. String strLimit = res.getResponseHeader("X-Rate-Limit-Limit"); if (strLimit != null) { limit = Integer.parseInt(strLimit); } else { return null; } String remaining = res.getResponseHeader("X-Rate-Limit-Remaining"); if (remaining != null) { remainingHits = Integer.parseInt(remaining); } else { return null; } String reset = res.getResponseHeader("X-Rate-Limit-Reset"); if (reset != null) { long longReset = Long.parseLong(reset); resetTimeInSeconds = (int) longReset; } else { return null; } return new RateLimitStatusJSONImpl(limit, remainingHits, resetTimeInSeconds); } /** * {@inheritDoc} */ @Override public int getRemaining() { return remaining; } /** * {@inheritDoc} */ @Override public int getRemainingHits() { return getRemaining(); } /** * {@inheritDoc} */ @Override public int getLimit() { return limit; } /** * {@inheritDoc} */ @Override public int getResetTimeInSeconds() { return resetTimeInSeconds; } /** * {@inheritDoc} */ @Override public int getSecondsUntilReset() { return secondsUntilReset; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; RateLimitStatusJSONImpl that = (RateLimitStatusJSONImpl) o; if (limit != that.limit) return false; if (remaining != that.remaining) return false; if (resetTimeInSeconds != that.resetTimeInSeconds) return false; if (secondsUntilReset != that.secondsUntilReset) return false; return true; } @Override public int hashCode() { int result = remaining; result = 31 * result + limit; result = 31 * result + resetTimeInSeconds; result = 31 * result + secondsUntilReset; return result; } @Override public String toString() { return "RateLimitStatusJSONImpl{" + "remaining=" + remaining + ", limit=" + limit + ", resetTimeInSeconds=" + resetTimeInSeconds + ", secondsUntilReset=" + secondsUntilReset + '}'; } }