package com.arrownock.opensource.arrownockers.utils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
import android.annotation.SuppressLint;
import android.util.Log;
import com.activeandroid.Model;
import com.activeandroid.annotation.Column;
import com.activeandroid.annotation.Table;
import com.activeandroid.query.Delete;
import com.activeandroid.query.Select;
import com.activeandroid.query.Update;
import com.arrownock.opensource.arrownockers.topic.Message;
import com.arrownock.opensource.arrownockers.topic.MessageEntity.EntityType;
import com.arrownock.opensource.arrownockers.topic.Topic;
import com.arrownock.mrm.MRMJSONResponseHandler;
public class DBManager {
private static final String logTag = "DBManager";
@Table(name = "User")
public static class User extends Model {
@Column(name = "username")
public String username;
@Column(name = "realname")
public String realname;
@Column(name = "clientId")
public String clientId;
}
@Table(name = "Session")
public static class Session extends Model {
@Column(name = "currentClientId")
public String currentClientId;
@Column(name = "clientIds")
public String clientIds;
@Column(name = "realnames")
public String realnames;
@Column(name = "updateTime")
public String updateTime;
@Column(name = "lastMessage")
public String lastMessage;
@Column(name = "status")
public String status;
@Column(name = "id")
public int id;
}
// 一对一聊天的消息
@Table(name = "Chat")
public static class Chat extends Model {
@Column(name = "message")
public String message;
@Column(name = "binary")
public byte[] binary;
@Column(name = "type")
public String type; // text, image, audio, location
@Column(name = "time")
public String time;
@Column(name = "fromClientId")
public String fromClientId;
@Column(name = "parties")
public String parties;
@Column(name = "topicId")
public String topicId;
@Column(name = "latitude")
public double latitude;
@Column(name = "longitude")
public double longitude;
@Column(name = "income")
public boolean income;
@Column(name = "status")
public String status; // sending, sent, received, read
@Column(name = "messageId")
public String messageId;
@Column(name = "currentClientId")
public String currentClientId;
@Column(name = "realname")
public String realname;
}
@Table(name = "Push")
public static class Push extends Model {
@Column(name = "clientId")
public String clientId;
@Column(name = "channel")
public String channel;
@Column(name = "title")
public String title;
@Column(name = "message")
public String message;
@Column(name = "binary")
public byte[] binary;
@Column(name = "dataType")
public String dataType;
@Column(name = "type")
public String type;
@Column(name = "time")
public String time;
@Column(name = "latitude")
public double latitude;
@Column(name = "longitude")
public double longitude;
@Column(name = "income")
public boolean income;
@Column(name = "status")
public String status;
@Column(name = "messageId")
public String messageId;
@Column(name = "batchNumber")
public String batchNumber;
@Column(name = "path")
public String path;
@Column(name = "currentUsername")
public String currentUsername;
}
@Table(name = "Topic")
public static class DBTopic extends Model {
@Column(name = "topicId")
public String topicId;
@Column(name = "topicName")
public String topicName;
@Column(name = "count")
public int count;
@Column(name = "lastMessage")
public String lastMessage;
@Column(name = "lastTime")
public long lastTime;
@Column(name = "unread")
public boolean unread;
@Column(name = "ownerUsername")
public String ownerUsername;
}
// 群组聊天
@Table(name = "Message")
public static class DBMessage extends Model {
@Column(name = "messageId")
public String messageId;
@Column(name = "username")
public String username;
@Column(name = "topicId")
public String topicId;
@Column(name = "contentString")
public String contentString;
@Column(name = "contentImage")
public byte[] contentImage;
@Column(name = "contentAudio")
public byte[] contentAudio;
@Column(name = "contentType")
public int contentType; // 0:text, 1:image, 2:audio
@Column(name = "time")
public long time;
@Column(name = "incoming")
public boolean incoming;
@Column(name = "unread")
public boolean unread;
@Column(name = "unsent")
public boolean unsent;
@Column(name = "ownerUsername")
public String ownerUsername;
}
public static void writeUser(String username, String realname,
String clientId) {
Log.i(logTag, "writeUser: " + username);
try {
User user = new User();
user.username = username;
user.realname = realname;
user.clientId = clientId;
user.save();
} catch (Exception e) {
e.printStackTrace();
}
}
public static User readUserByUsername(String username) {
Log.i(logTag, "readUserByUsername: " + username);
User user = null;
try {
user = new Select().from(User.class)
.where("username = ?", username).executeSingle();
} catch (Exception e) {
e.printStackTrace();
}
return user;
}
public static User readUserByClientId(String clientId) {
Log.i(logTag, "readUserByClientId: " + clientId);
User user = null;
try {
user = new Select().from(User.class)
.where("clientId = ?", clientId).executeSingle();
} catch (Exception e) {
e.printStackTrace();
}
return user;
}
public static Topic readOneTopic(String topicId) {
Log.i(logTag, "readOneTopic");
try {
List<DBTopic> dbTopics = new Select()
.from(DBTopic.class)
.where("ownerUsername = ? AND topicId = ?",
AnUtils.getCurrentUsername(), topicId).execute();
DBTopic dbTopic = dbTopics.get(0);
Topic topic = new Topic();
topic.topicId = dbTopic.topicId;
topic.topicName = dbTopic.topicName;
topic.count = dbTopic.count;
topic.lastTime = new Date(dbTopic.lastTime);
topic.lastMessage = dbTopic.lastMessage;
topic.unread = dbTopic.unread;
return topic;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@SuppressLint("DefaultLocale")
public static List<Topic> readAllTopics() {
Log.i(logTag, "readAllTopics");
try {
List<Topic> topics = new ArrayList<Topic>();
List<DBTopic> dbTopics = new Select()
.from(DBTopic.class)
.where("ownerUsername = ? Order By topicId",
AnUtils.getCurrentUsername()).execute();
for (DBTopic dbTopic : dbTopics) {
String query = String
.format("ownerUsername = \"%s\" AND topicId = \"%s\" AND incoming = 1 Order By time Desc Limit 1",
AnUtils.getCurrentUsername(), dbTopic.topicId);
List<DBMessage> dbmessages = new Select().from(DBMessage.class)
.where(query).execute();
if (dbmessages.size() > 0) {
DBMessage dbmessage = dbmessages.get(0);
dbTopic.lastTime = dbmessage.time;
dbTopic.unread = dbmessage.unread;
String lastMessage = dbmessage.username + ": ";
if (dbmessage.contentType == 0) {
lastMessage += dbmessage.contentString;
} else if (dbmessage.contentType == 1) {
lastMessage += "发来了一张图片";
} else if (dbmessage.contentType == 2) {
lastMessage += "发来了一段语音";
}
dbTopic.lastMessage = lastMessage;
}
Topic topic = new Topic();
topic.topicId = dbTopic.topicId;
topic.topicName = dbTopic.topicName;
topic.count = dbTopic.count;
topic.lastTime = new Date(dbTopic.lastTime);
topic.lastMessage = dbTopic.lastMessage;
topic.unread = dbTopic.unread;
topics.add(topic);
}
return topics;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void overwriteAllTopics(List<JSONObject> topicjJsonObjects) {
Log.i(logTag, "overwriteAllTopics");
try {
List<Topic> existingTopics = DBManager.readAllTopics();
List<Topic> serverTopics = new ArrayList<Topic>();
List<Topic> allTopics = new ArrayList<Topic>();
// 得到Server上的所有Topic
for (JSONObject topicJsonObject : topicjJsonObjects) {
Topic topic = new Topic();
try {
topic.topicId = topicJsonObject.getString("id");
topic.topicName = topicJsonObject.getString("name");
topic.count = topicJsonObject.getInt("parties_count");
topic.lastMessage = "没有任何消息";
topic.lastTime = new Date(0);
topic.unread = false;
} catch (Exception e) {
Log.e(logTag, "overwriteAllTopics");
e.printStackTrace();
}
serverTopics.add(topic);
}
// 找出本地不存在的那些新Topic
for (Topic serverTopic : serverTopics) {
boolean isNew = true;
for (Topic existingTopic : existingTopics) {
if (existingTopic.topicId.equals(serverTopic.topicId)) {
isNew = false;
break;
}
}
if (isNew) {
allTopics.add(serverTopic);
}
}
// 更新每一个Topic下的人数
for (Topic existingTopic : existingTopics) {
for (Topic serverTopic : serverTopics) {
if (existingTopic.topicId.equals(serverTopic.topicId)) {
existingTopic.count = serverTopic.count;
existingTopic.topicName = serverTopic.topicName;
break;
}
}
allTopics.add(existingTopic);
}
Map<String, Topic> topicMap = new HashMap<String, Topic>();
for (Topic topic : allTopics) {
try {
topicMap.put(topic.topicId, topic);
} catch (Exception e) {
e.printStackTrace();
}
}
allTopics = new ArrayList<Topic>(topicMap.values());
new Delete().from(DBTopic.class)
.where("ownerUsername = ?", AnUtils.getCurrentUsername())
.execute();
for (Topic topic : allTopics) {
DBTopic dbTopic = new DBTopic();
dbTopic.topicId = topic.topicId;
dbTopic.topicName = topic.topicName;
dbTopic.count = topic.count;
dbTopic.lastMessage = topic.lastMessage;
dbTopic.lastTime = topic.lastTime.getTime();
dbTopic.unread = topic.unread;
dbTopic.ownerUsername = AnUtils.getCurrentUsername();
dbTopic.save();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void writeMessage(Message message) {
try {
DBMessage dbmessage = new DBMessage();
dbmessage.messageId = message.messageId;
dbmessage.topicId = message.topicId;
dbmessage.incoming = message.isIncoming;
dbmessage.unread = message.isUnread;
dbmessage.unsent = message.isUnsent;
dbmessage.username = message.username;
dbmessage.time = message.timestamp.getTime();
dbmessage.contentString = message.content;
dbmessage.contentImage = message.imageData;
dbmessage.contentAudio = message.audioData;
if (message.type == EntityType.ET_TEXT) {
dbmessage.contentType = 0;
} else if (message.type == EntityType.ET_IMAGE) {
dbmessage.contentType = 1;
} else if (message.type == EntityType.ET_AUDIO) {
dbmessage.contentType = 2;
}
dbmessage.ownerUsername = AnUtils.getCurrentUsername();
dbmessage.save();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void deleteMessage(String messageId) {
try {
new Delete()
.from(DBMessage.class)
.where("ownerUsername = ? AND messageId = ?",
AnUtils.getCurrentUsername(), messageId).execute();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void updateOutgoingMessageAsSent(final String messageId) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
String query = String.format(
"ownerUsername = \"%s\" AND messageId = \"%s\"",
AnUtils.getCurrentUsername(), messageId);
new Update(DBMessage.class).set("unsent = ?", false)
.where(query).execute();
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
}
public static void updateIncomingMessageAsRead(final String messageId) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
String query = String.format(
"ownerUsername = \"%s\" AND messageId = \"%s\"",
AnUtils.getCurrentUsername(), messageId);
new Update(DBMessage.class).set("unread = ?", false)
.where(query).execute();
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
}
@SuppressLint("DefaultLocale")
public static List<Message> readMessages(String topicId, long beforeWhen,
int count) {
Log.i(logTag, "readMessages topicId: " + topicId);
try {
List<Message> messages = new ArrayList<Message>();
String query = null;
try {
if (beforeWhen > 0) {
query = String
.format("ownerUsername = \"%s\" AND topicId = \"%s\" AND time < %d Order By time Desc Limit %d",
AnUtils.getCurrentUsername(), topicId,
beforeWhen - 10, count);
} else {
query = String
.format("ownerUsername = \"%s\" AND topicId = \"%s\" Order By time Desc Limit %d",
AnUtils.getCurrentUsername(), topicId,
count);
}
} catch (Exception e) {
e.printStackTrace();
return messages;
}
List<DBMessage> dbMessages = new Select().from(DBMessage.class)
.where(query).execute();
Collections.reverse(dbMessages);
for (DBMessage dbMessage : dbMessages) {
Message message = new Message();
message.messageId = dbMessage.messageId;
message.topicId = dbMessage.topicId;
message.isIncoming = dbMessage.incoming;
message.isUnread = dbMessage.unread;
message.isUnsent = dbMessage.unsent;
message.username = dbMessage.username;
message.timestamp = new Date(dbMessage.time);
message.content = dbMessage.contentString;
message.imageData = dbMessage.contentImage;
message.audioData = dbMessage.contentAudio;
switch (dbMessage.contentType) {
case 0:
message.type = EntityType.ET_TEXT;
break;
case 1:
message.type = EntityType.ET_IMAGE;
break;
case 2:
message.type = EntityType.ET_AUDIO;
break;
default:
break;
}
messages.add(message);
}
return messages;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static List<Session> getAngelSession(String clientId) {
try {
return new Select()
.from(Session.class)
.where("currentClientId = ? AND realnames = ?", clientId,
"Angel").execute();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static List<Session> getSessions(String clientId) {
try {
return new Select().from(Session.class)
.where("currentClientId = ?", clientId).execute();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static List<Session> getSession(List<String> clientIds) {
try {
Collections.sort(clientIds);
return new Select()
.from(Session.class)
.where("currentClientId = ? AND clientIds = ?",
AnUtils.getCurrentClientId(),
StringUtils.join(clientIds, ",")).execute();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static boolean addSession(List<String> clientIds) {
try {
if (DBManager.getSession(clientIds).size() > 0) {
return false;
}
Collections.sort(clientIds);
List<String> queryClientIds = new ArrayList<String>();
for (String clientId : clientIds) {
queryClientIds.add("\"" + clientId + "\"");
}
Session session = new Session();
session.currentClientId = AnUtils.getCurrentClientId();
session.clientIds = StringUtils.join(clientIds, ",");
session.realnames = DBManager.readUserByClientId(session.clientIds).realname;
session.lastMessage = null;
session.updateTime = AnUtils.getTimeString(new Date());
session.save();
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public static boolean addSession(final List<String> clientIds,
final String username, final String time, final String message,
final String status) {
try {
if (DBManager.getSession(clientIds).size() > 0) {
return false;
}
Collections.sort(clientIds);
List<String> queryClientIds = new ArrayList<String>();
for (String clientId : clientIds) {
queryClientIds.add("\"" + clientId + "\"");
}
// 查找该用户的clientId
User user = DBManager.readUserByUsername(username);
if (user == null) {
try {
JSONObject params = new JSONObject();
params.put("username", username);
MRMWrapper.getMRM(AnUtils.applicationContext)
.sendPostRequest(AnUtils.applicationContext,
"users/search", params,
new MRMJSONResponseHandler() {
@Override
public void onFailure(Throwable arg0,
JSONObject arg1) {
Log.i(logTag,
"retrive user info of incoming new session failed");
}
@Override
public void onSuccess(int arg0,
JSONObject arg1) {
try {
JSONObject userJsonObject = arg1
.getJSONObject(
"response")
.getJSONArray("users")
.getJSONObject(0);
String realname = null;
if (userJsonObject
.has("realname")) {
realname = userJsonObject
.getString("realname");
} else {
realname = username;
}
Session session = new Session();
session.currentClientId = AnUtils
.getCurrentClientId();
session.clientIds = StringUtils
.join(clientIds, ",");
session.realnames = realname;
session.lastMessage = message;
session.updateTime = time;
session.status = status;
session.save();
if (AnIMWrapper.sessionActivity != null
&& AnIMWrapper.sessionActivity.alive) {
AnIMWrapper.sessionActivity
.initData();
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
} else {
Session session = new Session();
session.currentClientId = AnUtils.getCurrentClientId();
session.clientIds = StringUtils.join(clientIds, ",");
session.realnames = DBManager
.readUserByClientId(session.clientIds).realname;
session.lastMessage = message;
session.updateTime = time;
session.status = status;
session.save();
}
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public static boolean setSessionRead(List<String> clientIds) {
try {
List<Session> sessions = DBManager.getSession(clientIds);
if (sessions.size() > 0) {
Session s = sessions.get(0);
s.status = "read";
s.save();
}
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public static boolean setSessionUnread(List<String> clientIds,
String updateTime, String lastMessage) {
try {
List<Session> sessions = DBManager.getSession(clientIds);
if (sessions.size() > 0) {
Session s = sessions.get(0);
s.status = "unread";
s.updateTime = updateTime;
s.lastMessage = lastMessage;
s.save();
return true;
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public static List<Chat> getAllChats(String queryString, String key) {
try {
return new Select()
.from(Chat.class)
.where(key + " = " + "\"" + queryString + "\""
+ " AND currentClientId = " + "\""
+ AnUtils.getCurrentClientId() + "\"")
.orderBy("time").execute();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void addChat(Chat chat) {
try {
chat.currentClientId = AnUtils.getCurrentClientId();
chat.save();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void updateChatStatus(String messageId, boolean income,
String status) {
try {
Chat chat = new Select()
.from(Chat.class)
.where("messageId = ? AND income = ? AND currentClientId = ?",
messageId, income ? 1 : 0,
AnUtils.getCurrentClientId()).executeSingle();
if (chat == null) {
return;
}
if (chat.status.equals("read")) {
return;
}
chat.status = status;
chat.save();
} catch (Exception e) {
e.printStackTrace();
}
}
public static List<Push> getPushes(String channel) {
try {
return new Select()
.from(Push.class)
.where("title = ? AND currentUsername = ?", channel,
AnUtils.getCurrentUsername()).execute();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static List<Push> getUnreadPushes(String channel) {
try {
return new Select()
.from(Push.class)
.where("channel = ? AND status = ? AND currentUsername = ? order by time desc",
channel, "unread", AnUtils.getCurrentUsername())
.execute();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void addPush(Push push) {
try {
push.currentUsername = AnUtils.getCurrentUsername();
push.save();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void setPushRead(String title) {
try {
List<Push> unreadPushesList = new Select()
.from(Push.class)
.where("title = ? AND status = ? AND currentUsername = ?",
title, "unread", AnUtils.getCurrentUsername())
.execute();
for (int i = 0; i < unreadPushesList.size(); i++) {
Push push = unreadPushesList.get(i);
push.status = "read";
push.save();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void clear() {
try {
new Delete().from(Chat.class).execute();
new Delete().from(Push.class).execute();
new Delete().from(DBTopic.class).execute();
new Delete().from(DBMessage.class).execute();
new Delete().from(Session.class).where("realnames <> ?", "Angel")
.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
}