DatabaseBackend.java

  1package eu.siacs.conversations.persistance;
  2
  3import java.util.ArrayList;
  4import java.util.List;
  5import java.util.UUID;
  6import java.util.concurrent.CopyOnWriteArrayList;
  7
  8import eu.siacs.conversations.entities.Account;
  9import eu.siacs.conversations.entities.Contact;
 10import eu.siacs.conversations.entities.Conversation;
 11import eu.siacs.conversations.entities.Message;
 12import eu.siacs.conversations.entities.Presences;
 13import android.content.ContentValues;
 14import android.content.Context;
 15import android.database.Cursor;
 16import android.database.sqlite.SQLiteDatabase;
 17import android.database.sqlite.SQLiteOpenHelper;
 18import android.os.Bundle;
 19import android.util.Log;
 20
 21public class DatabaseBackend extends SQLiteOpenHelper {
 22
 23	private static DatabaseBackend instance = null;
 24
 25	private static final String DATABASE_NAME = "history";
 26	private static final int DATABASE_VERSION = 2;
 27
 28	public DatabaseBackend(Context context) {
 29		super(context, DATABASE_NAME, null, DATABASE_VERSION);
 30	}
 31
 32	@Override
 33	public void onCreate(SQLiteDatabase db) {
 34		db.execSQL("PRAGMA foreign_keys=ON;");
 35		db.execSQL("create table " + Account.TABLENAME + "(" + Account.UUID
 36				+ " TEXT PRIMARY KEY," + Account.USERNAME + " TEXT,"
 37				+ Account.SERVER + " TEXT," + Account.PASSWORD + " TEXT,"
 38				+ Account.ROSTERVERSION + " TEXT," + Account.OPTIONS
 39				+ " NUMBER, "+Account.KEYS+" TEXT)");
 40		db.execSQL("create table " + Conversation.TABLENAME + " ("
 41				+ Conversation.UUID + " TEXT PRIMARY KEY, " + Conversation.NAME
 42				+ " TEXT, " + Conversation.CONTACT + " TEXT, "
 43				+ Conversation.ACCOUNT + " TEXT, " + Conversation.CONTACTJID
 44				+ " TEXT, " + Conversation.CREATED + " NUMBER, "
 45				+ Conversation.STATUS + " NUMBER," + Conversation.MODE
 46				+ " NUMBER," + "FOREIGN KEY(" + Conversation.ACCOUNT
 47				+ ") REFERENCES " + Account.TABLENAME + "(" + Account.UUID
 48				+ ") ON DELETE CASCADE);");
 49		db.execSQL("create table " + Message.TABLENAME + "( " + Message.UUID
 50				+ " TEXT PRIMARY KEY, " + Message.CONVERSATION + " TEXT, "
 51				+ Message.TIME_SENT + " NUMBER, " + Message.COUNTERPART
 52				+ " TEXT, " + Message.BODY + " TEXT, " + Message.ENCRYPTION
 53				+ " NUMBER, " + Message.STATUS + " NUMBER," + "FOREIGN KEY("
 54				+ Message.CONVERSATION + ") REFERENCES "
 55				+ Conversation.TABLENAME + "(" + Conversation.UUID
 56				+ ") ON DELETE CASCADE);");
 57		db.execSQL("create table " + Contact.TABLENAME + "(" + Contact.UUID
 58				+ " TEXT PRIMARY KEY, " + Contact.ACCOUNT + " TEXT, "
 59				+ Contact.DISPLAYNAME + " TEXT," + Contact.JID + " TEXT,"
 60				+ Contact.PRESENCES + " TEXT, " + Contact.KEYS
 61				+ " TEXT," + Contact.PHOTOURI + " TEXT," + Contact.SUBSCRIPTION
 62				+ " NUMBER," + Contact.SYSTEMACCOUNT + " NUMBER, "
 63				+ "FOREIGN KEY(" + Contact.ACCOUNT + ") REFERENCES "
 64				+ Account.TABLENAME + "(" + Account.UUID
 65				+ ") ON DELETE CASCADE);");
 66	}
 67
 68	@Override
 69	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
 70		if (oldVersion < 2 && newVersion >= 2) {
 71			// enable compression by default.
 72			db.execSQL("update " + Account.TABLENAME
 73				+ " set " + Account.OPTIONS + " = " + Account.OPTIONS + " | 8");
 74		}
 75	}
 76
 77	public static synchronized DatabaseBackend getInstance(Context context) {
 78		if (instance == null) {
 79			instance = new DatabaseBackend(context);
 80		}
 81		return instance;
 82	}
 83
 84	public void createConversation(Conversation conversation) {
 85		SQLiteDatabase db = this.getWritableDatabase();
 86		db.insert(Conversation.TABLENAME, null, conversation.getContentValues());
 87	}
 88
 89	public void createMessage(Message message) {
 90		SQLiteDatabase db = this.getWritableDatabase();
 91		db.insert(Message.TABLENAME, null, message.getContentValues());
 92	}
 93
 94	public void createAccount(Account account) {
 95		SQLiteDatabase db = this.getWritableDatabase();
 96		db.insert(Account.TABLENAME, null, account.getContentValues());
 97	}
 98	
 99	public void createContact(Contact contact) {
100		SQLiteDatabase db = this.getWritableDatabase();
101		db.insert(Contact.TABLENAME, null, contact.getContentValues());
102	}
103
104	public int getConversationCount() {
105		SQLiteDatabase db = this.getReadableDatabase();
106		Cursor cursor = db.rawQuery("select count(uuid) as count from "
107				+ Conversation.TABLENAME + " where " + Conversation.STATUS
108				+ "=" + Conversation.STATUS_AVAILABLE, null);
109		cursor.moveToFirst();
110		return cursor.getInt(0);
111	}
112
113	public List<Conversation> getConversations(int status) {
114		List<Conversation> list = new ArrayList<Conversation>();
115		SQLiteDatabase db = this.getReadableDatabase();
116		String[] selectionArgs = { "" + status };
117		Cursor cursor = db.rawQuery("select * from " + Conversation.TABLENAME
118				+ " where " + Conversation.STATUS + " = ? order by "
119				+ Conversation.CREATED + " desc", selectionArgs);
120		while (cursor.moveToNext()) {
121			list.add(Conversation.fromCursor(cursor));
122		}
123		return list;
124	}
125
126	public List<Message> getMessages(Conversation conversation, int limit) {
127		List<Message> list = new CopyOnWriteArrayList<Message>();
128		SQLiteDatabase db = this.getReadableDatabase();
129		String[] selectionArgs = { conversation.getUuid() };
130		Cursor cursor = db.query(Message.TABLENAME, null, Message.CONVERSATION
131				+ "=?", selectionArgs, null, null, Message.TIME_SENT + " DESC",
132				String.valueOf(limit));
133		if (cursor.getCount() > 0) {
134			cursor.moveToLast();
135			do {
136				list.add(Message.fromCursor(cursor));
137			} while (cursor.moveToPrevious());
138		}
139		return list;
140	}
141
142	public Conversation findConversation(Account account, String contactJid) {
143		SQLiteDatabase db = this.getReadableDatabase();
144		String[] selectionArgs = { account.getUuid(), contactJid+"%" };
145		Cursor cursor = db.query(Conversation.TABLENAME, null,
146				Conversation.ACCOUNT + "=? AND " + Conversation.CONTACTJID + " like ?",
147				selectionArgs, null, null, null);
148		if (cursor.getCount() == 0)
149			return null;
150		cursor.moveToFirst();
151		return Conversation.fromCursor(cursor);
152	}
153
154	public void updateConversation(Conversation conversation) {
155		SQLiteDatabase db = this.getWritableDatabase();
156		String[] args = { conversation.getUuid() };
157		db.update(Conversation.TABLENAME, conversation.getContentValues(),
158				Conversation.UUID + "=?", args);
159	}
160
161	public List<Account> getAccounts() {
162		List<Account> list = new ArrayList<Account>();
163		SQLiteDatabase db = this.getReadableDatabase();
164		Cursor cursor = db.query(Account.TABLENAME, null, null, null, null,
165				null, null);
166		Log.d("gultsch", "found " + cursor.getCount() + " accounts");
167		while (cursor.moveToNext()) {
168			list.add(Account.fromCursor(cursor));
169		}
170		return list;
171	}
172
173	public void updateAccount(Account account) {
174		SQLiteDatabase db = this.getWritableDatabase();
175		String[] args = { account.getUuid() };
176		db.update(Account.TABLENAME, account.getContentValues(), Account.UUID
177				+ "=?", args);
178	}
179
180	public void deleteAccount(Account account) {
181		SQLiteDatabase db = this.getWritableDatabase();
182		String[] args = { account.getUuid() };
183		db.delete(Account.TABLENAME, Account.UUID + "=?", args);
184	}
185
186	@Override
187	public SQLiteDatabase getWritableDatabase() {
188		SQLiteDatabase db = super.getWritableDatabase();
189		db.execSQL("PRAGMA foreign_keys=ON;");
190		return db;
191	}
192
193	public void updateMessage(Message message) {
194		SQLiteDatabase db = this.getWritableDatabase();
195		String[] args = { message.getUuid() };
196		db.update(Message.TABLENAME, message.getContentValues(), Message.UUID
197				+ "=?", args);
198	}
199	
200	public void updateContact(Contact contact) {
201		SQLiteDatabase db = this.getWritableDatabase();
202		String[] args = { contact.getUuid() };
203		db.update(Contact.TABLENAME, contact.getContentValues(), Contact.UUID
204				+ "=?", args);
205	}
206	
207	public void clearPresences(Account account) {
208		SQLiteDatabase db = this.getWritableDatabase();
209		String[] args = { account.getUuid() };
210		ContentValues values = new ContentValues();
211		values.put(Contact.PRESENCES,"[]");
212		db.update(Contact.TABLENAME, values, Contact.ACCOUNT
213				+ "=?", args);
214	}
215	
216	public void mergeContacts(List<Contact> contacts) {
217		SQLiteDatabase db = this.getWritableDatabase();
218		for (int i = 0; i < contacts.size(); i++) {
219			Contact contact = contacts.get(i);
220			String[] columns = {Contact.UUID, Contact.PRESENCES};
221			String[] args = {contact.getAccount().getUuid(), contact.getJid()};
222			Cursor cursor = db.query(Contact.TABLENAME, columns,Contact.ACCOUNT+"=? AND "+Contact.JID+"=?", args, null, null, null);
223			if (cursor.getCount()>=1) {
224				cursor.moveToFirst();
225				contact.setUuid(cursor.getString(0));
226				contact.setPresences(Presences.fromJsonString(cursor.getString(1)));
227				updateContact(contact);
228			} else {
229				contact.setUuid(UUID.randomUUID().toString());
230				createContact(contact);
231			}
232		}
233	}
234
235	public List<Contact> getContactsByAccount(Account account) {
236		List<Contact> list = new ArrayList<Contact>();
237		SQLiteDatabase db = this.getReadableDatabase();
238		Cursor cursor;
239		if (account==null) {
240			cursor = db.query(Contact.TABLENAME, null, null, null, null,
241					null, null);
242		} else {
243			String args[] = {account.getUuid()};
244			cursor = db.query(Contact.TABLENAME, null, Contact.ACCOUNT+"=?", args, null,
245					null, null);
246		}
247		while (cursor.moveToNext()) {
248			list.add(Contact.fromCursor(cursor));
249		}
250		return list;
251	}
252	
253	public List<Contact> getContacts(String where) {
254		List<Contact> list = new ArrayList<Contact>();
255		SQLiteDatabase db = this.getReadableDatabase();
256		Cursor cursor = db.query(Contact.TABLENAME, null, where, null, null, null, null);
257		while (cursor.moveToNext()) {
258			list.add(Contact.fromCursor(cursor));
259		}
260		return list;
261	}
262
263	public Contact findContact(Account account, String jid) {
264		SQLiteDatabase db = this.getReadableDatabase();
265		String[] selectionArgs = { account.getUuid(), jid };
266		Cursor cursor = db.query(Contact.TABLENAME, null,
267				Contact.ACCOUNT + "=? AND " + Contact.JID + "=?",
268				selectionArgs, null, null, null);
269		if (cursor.getCount() == 0)
270			return null;
271		cursor.moveToFirst();
272		return Contact.fromCursor(cursor);
273	}
274
275	public void deleteMessage(Message message) {
276		SQLiteDatabase db = this.getWritableDatabase();
277		String[] args = { message.getUuid() };
278		db.delete(Message.TABLENAME, Message.UUID + "=?", args);
279	}
280
281	public void deleteContact(Contact contact) {
282		SQLiteDatabase db = this.getWritableDatabase();
283		String[] args = { contact.getUuid() };
284		db.delete(Contact.TABLENAME, Contact.UUID + "=?", args);
285	}
286
287	public Contact getContact(String uuid) {
288		SQLiteDatabase db = this.getWritableDatabase();
289		String[] args = { uuid };
290		Cursor cursor = db.query(Contact.TABLENAME, null, Contact.UUID + "=?", args, null, null, null);
291		if (cursor.getCount() == 0)
292			return null;
293		cursor.moveToFirst();
294		return Contact.fromCursor(cursor);
295	}
296
297	
298}