/* * Copyright (C) 2013 Chris Lacy * * 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 org.tweetalib.android.model; import org.appdotnet4j.model.AdnPost; import org.appdotnet4j.model.AdnPosts; import org.appdotnet4j.model.AdnUser; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.tweetalib.android.model.TwitterStatusesFilter.FilterType; import java.util.ArrayList; import java.util.Collections; import java.util.List; import twitter4j.QueryResult; import twitter4j.ResponseList; import twitter4j.Status; import twitter4j.User; public class TwitterStatuses { /* * */ public TwitterStatuses(TwitterStatuses another) { _mStatuses = new ArrayList<TwitterStatus>(another._mStatuses); mCounts = another.mCounts.clone(); mGetNewStatusesMaxId = another.mGetNewStatusesMaxId; } /* * */ public TwitterStatuses() { _mStatuses = new ArrayList<TwitterStatus>(); } /* * */ public TwitterStatuses(TwitterStatus status) { this(); add(status); } /* * */ private static final String KEY_STATUSES = "statuses"; public TwitterStatuses(String jsonAsString) { _mStatuses = new ArrayList<TwitterStatus>(); try { JSONObject object = new JSONObject(jsonAsString); if (object.has(KEY_STATUSES)) { String statusesAsString = object.getString(KEY_STATUSES); JSONArray jsonArray = new JSONArray(statusesAsString); for (int i = 0; i < jsonArray.length(); i++) { String statusString = jsonArray.getString(i); TwitterStatus status = new TwitterStatus(statusString); add(status); } } } catch (JSONException e) { e.printStackTrace(); } } /* * */ public String toString() { if (_mStatuses != null && _mStatuses.size() > 0) { JSONObject object = new JSONObject(); JSONArray statusArray = new JSONArray(); for (TwitterStatus status : _mStatuses) { statusArray.put(status.toString()); } try { object.put(KEY_STATUSES, statusArray); return object.toString(); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return null; } /* * */ public int getStatusCount() { return size(); } public int getStatusCount(TwitterStatusesFilter filter) { int size = size(); FilterType filterType = filter.getFilterType(); if (filterType != FilterType.ALL) { int filteredOut = mCounts[filterType.ordinal()]; size -= filteredOut; } return size; } /* * */ public TwitterStatus getStatus(int index) { return get(index); } /* * */ public TwitterStatus getStatus(int index, TwitterStatusesFilter filter) { FilterType filterType = filter.getFilterType(); if (filterType == FilterType.ALL) { return getStatus(index); } int size = size(); int filteredIndex = 0; // int filterCount = 0; for (int i = 0; i < size; i++) { TwitterStatus status = get(i); if (status != null) { boolean isReply = status.mInReplyToStatusId != null; boolean isRetweet = status.mIsRetweet; switch (filterType) { case HIDE_RETWEETS: if (isRetweet) { // filterCount += 1; continue; } break; case HIDE_REPLIES: if (isReply) { // filterCount += 1; continue; } break; case HIDE_RETWEETS_REPLIES: if (isReply || isRetweet) { // filterCount += 1; continue; } break; default: break; } if (filteredIndex == index) { return status; } filteredIndex += 1; } } // Log.d("done", "done (" + filterCount + ")"); return null; } /* * */ /* * public TwitterStatus getStatus(Iterator iterator) { if * (iterator.finished() == false) { return get(iterator.mLastIndex); } * return null; } */ /* * */ public void add(TwitterStatus status) { // TODO: Ensure no duplicates _mStatuses.add(status); updateCount(status); } /* * */ private void updateCount(TwitterStatus status) { if (status.mIsRetweet) { mCounts[FilterType.HIDE_RETWEETS.ordinal()] += 1; } if (status.mInReplyToStatusId != null) { mCounts[FilterType.HIDE_REPLIES.ordinal()] += 1; } if (status.mIsRetweet || status.mInReplyToStatusId != null) { mCounts[FilterType.HIDE_RETWEETS_REPLIES.ordinal()] += 1; } } /* * */ public void add(QueryResult result) { List<Status> tweets = result.getTweets(); if (tweets != null) { for (int i = 0; i < tweets.size(); i++) { Status tweet = tweets.get(i); add(new TwitterStatus(tweet)); } } sort(); } public void setFeedFullyRefreshed() { mGetNewStatusesMaxId = null; } /* * */ public interface AddUserCallback { public void addUser(User user); public void addUser(AdnUser user); } /* * */ public void add(ResponseList<twitter4j.Status> statuses, AddUserCallback addUserCallback) { TwitterStatus firstItem = size() > 0 ? get(0) : null; int addCount = 0; boolean stillMore = true; TwitterStatus lastAddedStatus = null; mGetNewStatusesMaxId = null; for (Status status : statuses) { if (firstItem != null && status.getId() == firstItem.mId) { stillMore = false; break; } lastAddedStatus = new TwitterStatus(status); add(lastAddedStatus); if (addUserCallback != null) { addUserCallback.addUser(status.getUser()); if (status.isRetweet()) { Status retweetedStatus = status.getRetweetedStatus(); if (retweetedStatus != null) { addUserCallback.addUser(retweetedStatus.getUser()); } } } addCount += 1; } if (stillMore && lastAddedStatus != null) { mGetNewStatusesMaxId = lastAddedStatus.mId; } if (addCount > 0) { sort(); } } /* * */ public void add(AdnPosts posts, AddUserCallback addUserCallback) { TwitterStatus firstItem = size() > 0 ? get(0) : null; int addCount = 0; boolean stillMore = true; TwitterStatus lastAddedStatus = null; mGetNewStatusesMaxId = null; for (AdnPost post : posts.mPosts) { if (firstItem != null && post.mId == firstItem.mId) { stillMore = false; break; } lastAddedStatus = new TwitterStatus(post); add(lastAddedStatus); if (addUserCallback != null) { addUserCallback.addUser(post.mUser); } addCount += 1; } if (stillMore && lastAddedStatus != null) { mGetNewStatusesMaxId = lastAddedStatus.mId; } if (addCount > 0) { sort(); } } /* * */ public void add(TwitterStatuses statuses) { TwitterStatus firstItem = size() > 0 ? get(0) : null; int addCount = 0; for (int i = 0; i < statuses.getStatusCount(); i++) { TwitterStatus status = statuses.getStatus(i); if (firstItem != null && status.mId == firstItem.mId) { break; } add(status); addCount += 1; } if (addCount > 0) { sort(); } } /* * */ public void add(TwitterStatus status, boolean sort) { add(status); if (sort) { sort(); } } /* * */ public void insert(TwitterStatuses statuses) { int addCount = 0; for (int i = 0; i < statuses.getStatusCount(); i++) { TwitterStatus status = statuses.getStatus(i); if (findByStatusId(status.mId) == null) { add(status); addCount += 1; } } if (addCount > 0) { sort(); } } /* * */ public void remove(TwitterStatuses statuses) { int size = size(); if (size != 0) { ArrayList<Integer> toRemoveList = new ArrayList<Integer>(); for (int existingIndex = 0; existingIndex < size; existingIndex++) { TwitterStatus user = get(existingIndex); for (int i = 0; i < statuses.getStatusCount(); i++) { TwitterStatus statusToRemove = statuses.getStatus(i); if (statusToRemove.mId == user.mId) { toRemoveList.add(existingIndex); } } } for (int toRemoveIndex : toRemoveList) { remove(toRemoveIndex); } } } /* * */ public void sort() { Collections.sort(_mStatuses); } /* * Find the given status ID in a list via a binary search. Assumes the list * is sorted. */ public TwitterStatus findByStatusId(long statusId) { Integer statusIndex = getStatusIndex(statusId); if (statusIndex != null) { return get(statusIndex.intValue()); } return null; } /* * */ public Integer getStatusIndex(long statusId) { if (size() == 0) { return null; } int low = 0; int high = size() - 1; while (low <= high) { int middle = ((low + high) / 2); TwitterStatus status = get(middle); if (statusId > status.mId) { high = middle - 1; } else if (statusId < status.mId) { low = middle + 1; } else if (statusId == status.mId) { // The element has been found return middle; } else { // Couldn't find the element break; } } //nest down to try and get the status by an original statusID. //Useful in situtations like a retweet of a retweet, where you don't have the statusId return getStatusIndexFromOriginalStatusId(statusId); } Integer getStatusIndexFromOriginalStatusId(long originalStatusId) { if (size() == 0) { return null; } //Since original status ids have no order, a long search through each is required. for (int i = 0; i < size(); i++) { TwitterStatus status = get(i); if (originalStatusId == status.mOriginalRetweetId) { return i; } } return null; } /* * */ private int size() { return _mStatuses.size(); } private TwitterStatus get(int index) { if (index >= _mStatuses.size()) { return null; } return _mStatuses.get(index); } private void remove(int index) { _mStatuses.remove(index); } /* * */ private final ArrayList<TwitterStatus> _mStatuses; private int[] mCounts = new int[FilterType.FILTER_MAX.ordinal()]; private Long mGetNewStatusesMaxId = null; public Long getNewStatusesMaxId() { return mGetNewStatusesMaxId; } /* * */ public void reset() { _mStatuses.clear(); mCounts = new int[FilterType.FILTER_MAX.ordinal()]; mGetNewStatusesMaxId = null; } }