/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2015 Umeng, Inc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.umeng.comm.core.db.ctrl.impl;
import android.text.TextUtils;
import com.activeandroid.Model;
import com.activeandroid.query.Delete;
import com.activeandroid.query.Select;
import com.umeng.comm.core.beans.CommUser;
import com.umeng.comm.core.beans.Comment;
import com.umeng.comm.core.beans.FeedItem;
import com.umeng.comm.core.beans.ImageItem;
import com.umeng.comm.core.beans.Like;
import com.umeng.comm.core.beans.Topic;
import com.umeng.comm.core.beans.relation.DBRelationOP;
import com.umeng.comm.core.beans.relation.EntityRelationFactory;
import com.umeng.comm.core.constants.Constants;
import com.umeng.comm.core.db.ctrl.FeedDBAPI;
import com.umeng.comm.core.listeners.Listeners.SimpleFetchListener;
import java.util.ArrayList;
import java.util.List;
/**
* 对feed在本地进行add、delete、query 操作。
*/
class FeedDBAPIImpl extends AbsDbAPI<List<FeedItem>> implements FeedDBAPI {
private int mOffset = 0;
private int mFeedCount = 0;
@Override
public void loadFeedsFromDB(final SimpleFetchListener<List<FeedItem>>
listener) {
submit(new DbCommand() {
@Override
protected void execute() {
initFeedsCount();
// 分页加载
List<FeedItem> items = new
Select().from(FeedItem.class).where("category= 'NORMAL'")
.limit(Constants.COUNT).offset(mOffset).orderBy("publishTime DESC")
.execute();
fillItems(items);
deliverResult(listener, items);
updateOffset();
}
});
}
@Override
public void loadFeedsFromDB(final String uid, final SimpleFetchListener<List<FeedItem>> listener) {
submit(new DbCommand() {
@Override
protected void execute() {
List<FeedItem> items = new Select().from(FeedItem.class).execute();
List<FeedItem> targetItems = filterFeedItems(items, uid);
fillItems(targetItems);
deliverResult(listener, targetItems);
}
});
}
private void initFeedsCount() {
if (mFeedCount == 0) {
mFeedCount = new Select().from(FeedItem.class).count();
}
}
private void updateOffset() {
if (mOffset + Constants.COUNT <= mFeedCount) {
mOffset += Constants.COUNT;
} else {
mOffset = mFeedCount;
}
}
private List<FeedItem> filterFeedItems(List<FeedItem> response, String uid) {
List<FeedItem> targetItems = new ArrayList<FeedItem>();
for (FeedItem feedItem : response) {
if (feedItem.creator.id.equals(uid)) {
targetItems.add(feedItem);
}
}
return targetItems;
}
@Override
public void saveFeedsToDB(List<FeedItem> feedItems) {
if (feedItems == null || feedItems.size() == 0) {
return;
}
final List<FeedItem> itertorItems = new ArrayList<FeedItem>(feedItems);
// 保存到数据库
submit(new DbCommand() {
@Override
protected void execute() {
for (FeedItem feedItem : itertorItems) {
if (feedItem.sourceFeed != null) {
saveFeedToDB(feedItem.sourceFeed);// 保存被转发的feed
}
// 保存feed
saveFeedToDB(feedItem);
}
}
});
}
@Override
public void deleteFeedFromDB(final String feedId) {
if (TextUtils.isEmpty(feedId)) {
return;
}
submit(new DbCommand() {
@Override
protected void execute() {
// 删除feed本身
new Delete().from(FeedItem.class).where("_id=?", feedId).execute();
// 删除跟feed相关的关系表
DBRelationOP<?> feedCreator = EntityRelationFactory.createFeedCreator();
feedCreator.deleteById(feedId);
DBRelationOP<?> feedFriends = EntityRelationFactory.createFeedFriends();
feedFriends.deleteById(feedId);
// 删除图片
deleteImagesForFeed(feedId);
DBRelationOP<?> feedTopic = EntityRelationFactory.createFeedTopic();
feedTopic.deleteById(feedId);
DBRelationOP<?> feedLike = EntityRelationFactory.createFeedLike();
feedLike.deleteById(feedId);
DBRelationOP<?> feedComment = EntityRelationFactory.createFeedComment();
feedComment.deleteById(feedId);
}
});
}
private void deleteImagesForFeed(String feedId) {
new Delete().from(ImageItem.class).where("feedId=?", feedId).execute();
}
@Override
public void deleteAllFeedsFromDB() {
submit(new DeleteAllFeedItemCmd());
}
@Override
public void queryFeedCount(final String uid, final SimpleFetchListener<Integer> listener) {
submit(new DbCommand() {
@Override
protected void execute() {
DBRelationOP<?> relationOP = EntityRelationFactory.createFeedCreator();
deliverResultForCount(listener, relationOP.queryCountById(uid));
}
});
}
/**
* 填充feed的相关数据</br>
*
* @param items
*/
private void fillItems(List<FeedItem> items) {
for (final FeedItem item : items) {
if (!TextUtils.isEmpty(item.sourceFeedId)) {
FeedItem feedItem = new Select().from(FeedItem.class)
.where("_id=?",
item.sourceFeedId)
.executeSingle();
fillOneItem(feedItem);// 填充源feed的数据
item.sourceFeed = feedItem;
}
fillOneItem(item);
}
}
/**
* 填充feed每项数据</br>
*
* @param item
*/
private void fillOneItem(FeedItem item) {
if (item == null) {
return;
}
DBRelationOP<CommUser> feedCreator = EntityRelationFactory.createFeedCreator();
DBRelationOP<List<CommUser>> feedFriends = EntityRelationFactory.createFeedFriends();
DBRelationOP<List<Topic>> feedTopic = EntityRelationFactory.createFeedTopic();
// DBRelationOP<List<Like>> feedLike =
// EntityRelationFactory.createFeedLike();
// DBRelationOP<List<Comment>> feedComment =
// EntityRelationFactory.createFeedComment();
item.creator = feedCreator.queryById(item.id);
item.atFriends = feedFriends.queryById(item.id);
item.imageUrls = selectImagesForFeed(item.id);
item.topics = feedTopic.queryById(item.id);
// item.likes = feedLike.queryById(item.id);
// item.comments = feedComment.queryById(item.id);
}
private List<ImageItem> selectImagesForFeed(String feedId) {
return new Select().from(ImageItem.class).where("feedId=?", feedId).execute();
}
@Override
public void saveFeedToDB(FeedItem feedItem) {
// 存储feed本身的信息
feedItem.saveEntity();
// 存储一些关联信息
saveRelationship(feedItem);
}
/**
* 存储feed的关系表,例如评论、@的好友、like等
*
* @param feedItem
*/
private void saveRelationship(FeedItem feedItem) {
DBRelationOP<CommUser> feedCreator = EntityRelationFactory.createFeedCreator(feedItem,
feedItem.creator);
feedCreator.saveEntity();
// 存储@的好友
List<CommUser> friends = new ArrayList<CommUser>(feedItem.atFriends);
for (CommUser friend : friends) {
DBRelationOP<?> feedFriends = EntityRelationFactory.createFeedFriends(feedItem, friend);
feedFriends.saveEntity();
}
// 存储feed所属的话题
List<Topic> topics = new ArrayList<Topic>(feedItem.topics);
for (Topic topic : topics) {
DBRelationOP<?> feedTopic = EntityRelationFactory.createFeedTopic(feedItem, topic);
feedTopic.saveEntity();
}
// 存储feed的赞
List<Like> likes = new ArrayList<Like>(feedItem.likes);
for (Like like : likes) {
DBRelationOP<?> feedLike = EntityRelationFactory.createFeedLike(feedItem, like);
feedLike.saveEntity();
}
// 存储feed的评论
List<Comment> comments = new ArrayList<Comment>(feedItem.comments);
for (Comment comment : comments) {
DBRelationOP<?> feedComment = EntityRelationFactory
.createFeedComment(feedItem, comment);
feedComment.saveEntity();
}
}
@Override
public void resetOffset() {
mOffset = 0;
}
@Override
public void loadRecommendFeedsFromDB(SimpleFetchListener<List<FeedItem>> listener) {
List<FeedItem> items = new Select().from(FeedItem.class)
.where("category='RECOMMEND'").execute();
fillItems(items);
deliverResult(listener, items);
}
@Override
public void loadFriendsFeedsFromDB(SimpleFetchListener<List<FeedItem>> listener) {
List<FeedItem> items = new Select().from(FeedItem.class)
.where("category='FRIENDS'").execute();
fillItems(items);
deliverResult(listener, items);
}
@Override
public void deleteAllRecommendFeed() {
new Delete().from(FeedItem.class).where("category='RECOMMEND'").execute();
}
@Override
public void deleteFriendFeed(String uid) {
if (TextUtils.isEmpty(uid)) {
return;
}
List<FeedItem> items = new Select().from(FeedItem.class)
.where("category='FRIENDS'").execute();
fillItems(items);
for (FeedItem item : items) {
if (item.creator.id.equals(uid)) {
deleteFeedFromDB(item.id);
}
}
}
@Override
public void deleteNearbyFeed() {
new Delete().from(FeedItem.class).where("category='NEARBY'").execute();
}
@Override
public void loadNearbyFeed(SimpleFetchListener<List<FeedItem>> listener) {
List<FeedItem> items = new Select().from(FeedItem.class)
.where("category='NEARBY'").execute();
fillItems(items);
deliverResult(listener, items);
}
@Override
public void loadFavoritesFeed(SimpleFetchListener<List<FeedItem>> listener) {
List<FeedItem> items = new Select().from(FeedItem.class)
.where("category='FAVORITES'").execute();
fillItems(items);
deliverResult(listener, items);
}
@Override
public void deleteFavoritesFeed(String feedId) {
new Delete().from(FeedItem.class).where("category='NEARBY'").and("feedId=?", feedId)
.execute();
}
/**
* 删除Feed相关的Like、评论、feed-topic、feed-friend等关系记录,评论、赞本书的数据也会被删除
*/
class DeleteAllFeedItemCmd extends DbCommand {
@Override
protected void execute() {
try {
removeFeedRelativeItems();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 删除Feed本身的数据
new Delete().from(FeedItem.class).where("category='NORMAL'").execute();
}
@SuppressWarnings("unchecked")
private Class<? extends Model> refectModelClz(String className)
throws ClassNotFoundException {
return (Class<? extends Model>) Class.forName(className);
}
private void removeFeedRelativeItems() throws ClassNotFoundException {
// 获取所有缓存的Feed
List<FeedItem> cacheFeedItems = new Select().from(FeedItem.class)
.where("category='NORMAL'").execute();
Class<? extends Model> feedLikeClass = refectModelClz("com.umeng.comm.core.beans.relation.FeedLike");
Class<? extends Model> feedCommentClass = refectModelClz("com.umeng.comm.core.beans.relation.FeedComment");
Class<? extends Model> feedTopicClass = refectModelClz("com.umeng.comm.core.beans.relation.FeedTopic");
Class<? extends Model> feedCreatorClass = refectModelClz("com.umeng.comm.core.beans.relation.FeedCreator");
Class<? extends Model> feedFriendClass = refectModelClz("com.umeng.comm.core.beans.relation.FeedFriends");
for (FeedItem feedItem : cacheFeedItems) {
// 移除like相关
removeRelativeLike(feedItem.id, feedLikeClass);
// 移除Feed相关的Comment
removeRelativeComment(feedItem.id, feedCommentClass);
new Delete().from(feedTopicClass).where("feed_id=?", feedItem.id)
.execute();
new Delete().from(feedCreatorClass).where("feed_id=?", feedItem.id)
.execute();
new Delete().from(feedFriendClass).where("feed_id=?", feedItem.id)
.execute();
}
}
private void removeRelativeLike(String feedId, Class<? extends Model> feedLikeClass)
throws ClassNotFoundException {
List<Like> likes = new Select().from(Like.class).innerJoin(feedLikeClass)
.on("like._id=feed_like.like_id").where("feed_like.feed_id=?", feedId)
.execute();
// 删除feed_like表中的记录
new Delete().from(feedLikeClass).where("feed_id=?", feedId);
Class<? extends Model> likeCreatorClz = feedLikeClass = refectModelClz("com.umeng.comm.core.beans.relation.LikeCreator");
for (Like like : likes) {
new Delete().from(likeCreatorClz).where("like_id=?", like.id).execute();
new Delete().from(Like.class).where("_id=?", like.id).execute();
}
}
private void removeRelativeComment(String feedId,
Class<? extends Model> feedCommentClass)
throws ClassNotFoundException {
List<Comment> comments = new Select().from(Comment.class)
.innerJoin(feedCommentClass)
.on("comment._id=feed_comment.comment_id")
.where("feed_comment.feed_id=?", feedId)
.execute();
for (Comment comment : comments) {
new Delete().from(feedCommentClass).where("comment_id=?", comment.id).execute();
new Delete().from(Comment.class).where("_id=?", comment.id).execute();
}
}
}
}