package com.gimranov.zandy.app.data; import java.util.ArrayList; import java.util.UUID; import org.json.JSONException; import org.json.JSONObject; import android.content.Context; import android.database.Cursor; import android.util.Log; import com.gimranov.zandy.app.task.APIRequest; public class Attachment { public String key; public String parentKey; public String etag; public int status; public String dbId; public String title; public String filename; public String url; /** * Queue of attachments that need to be synced, because they're dirty */ public static ArrayList<Attachment> queue; /** * APIRequest.API_DIRTY means that we'll try to push this version up to the server */ public String dirty; /** * Zotero's JSON format for attachment / child information * * linkMode: O = file attachment, in ZFS? * 1 = link attachment? */ public JSONObject content; private static final String TAG = "com.gimranov.zandy.app.data.Attachment"; public static final int AVAILABLE = 1; public static final int LOCAL = 2; public static final int UNKNOWN = 3; /* linkMode statuses from the Zotero client code this.LINK_MODE_IMPORTED_FILE = 0; this.LINK_MODE_IMPORTED_URL = 1; this.LINK_MODE_LINKED_FILE = 2; this.LINK_MODE_LINKED_URL = 3; */ public static final int MODE_LINKED_URL = 3; public static final int MODE_LINKED_FILE = 2; public static final int MODE_IMPORTED_URL = 1; public static final int MODE_IMPORTED_FILE = 0; public Attachment () { if (queue == null) queue = new ArrayList<Attachment>(); parentKey = title = filename = url = etag = dirty = ""; status = UNKNOWN; content = new JSONObject(); } public Attachment(Context c, String type, String parentKey) { this(); content = new JSONObject(); try { content.put("itemType", type); } catch (JSONException e) { Log.d(TAG,"JSON exception caught setting itemType in Attachment constructor", e); } key = UUID.randomUUID().toString(); this.parentKey = parentKey; dirty = APIRequest.API_NEW; } public String getType () { String type = ""; try { type = content.getString("itemType"); if (type.equals("attachment")) { if (content.has("mimeType")) { type = content.getString("mimeType"); } else if (content.has("contentType")) { type = content.getString("contentType"); } } if (type.equals("note")) type = "note"; } catch (JSONException e) { Log.e(TAG, "JSON exception parsing attachment content: "+ content.toString(), e); } return type; } public void setNoteText (String text) { try { content.put("note", text); } catch (JSONException e) { Log.e(TAG, "JSON exception setting note text",e); } } public void save(Database db) { Attachment existing = load(key, db); if (dbId == null && existing == null) { Log.d(TAG, "Saving new, with status: "+status); String[] args = { key, parentKey, title, filename, url, Integer.toString(status), etag, dirty, content.toString() }; Cursor cur = db .rawQuery( "insert into attachments (attachment_key, item_key, title, filename, url, status, etag, dirty, content) " + "values (?, ?, ?, ?, ?, ?, ?, ?, ?)", args); if (cur != null) cur.close(); Attachment fromDB = load(key, db); dbId = fromDB.dbId; } else { Log.d(TAG, "Updating attachment, with status: "+status+" and fn: "+filename); if (dbId == null) dbId = existing.dbId; String[] args = { key, parentKey, title, filename, url, Integer.toString(status), etag, dirty, content.toString(), dbId }; Cursor cur = db .rawQuery( "update attachments set attachment_key=?, item_key=?, title=?," + " filename=?, url=?, status=?, etag=?, dirty=?, " + " content=? " + " where _id=?", args); if (cur != null) cur.close(); } db.close(); } /** * Deletes an attachment from the database, keeping a record of it in the deleteditems table * We will then send out delete requests via the API to propagate the deletion */ public void delete(Database db) { String[] args = { dbId }; db.rawQuery("delete from attachments where _id=?", args); // Don't prepare deletion requests for unsynced new attachments if (!APIRequest.API_NEW.equals(dirty)) { String[] args2 = { key, etag }; db.rawQuery("insert into deleteditems (item_key, etag) values (?, ?)", args2); } } /** * Identifies dirty items in the database and queues them for syncing */ public static void queue(Database db) { if (queue == null) { // Initialize the queue if necessary queue = new ArrayList<Attachment>(); } Log.d(TAG, "Clearing attachment dirty queue before repopulation"); queue.clear(); Attachment attachment; String[] cols = Database.ATTCOLS; String[] args = { APIRequest.API_CLEAN }; Cursor cur = db.query("attachments", cols, "dirty != ?", args, null, null, null, null); if (cur == null) { Log.d(TAG, "No dirty attachments found in database"); queue.clear(); return; } do { Log.d(TAG, "Adding attachment to dirty queue"); attachment = load(cur); queue.add(attachment); } while (cur.moveToNext() != false); if (cur != null) cur.close(); } /** * Get an Attachment from the current cursor position. * * Does not close cursor. * * @param cur * @return */ public static Attachment load(Cursor cur) { if (cur == null) return null; Attachment a = new Attachment(); a.dbId = cur.getString(0); a.key = cur.getString(1); a.parentKey = cur.getString(2); a.title = cur.getString(3); a.filename = cur.getString(4); a.url = cur.getString(5); try { a.status = cur.getInt(6); } catch (Exception e) { a.status = UNKNOWN; } a.etag = cur.getString(7); a.dirty = cur.getString(8); try { a.content = new JSONObject(cur.getString(9)); } catch (JSONException e) { Log.e(TAG, "Caught JSON exception loading attachment from db", e); } return a; } public static Attachment load(String key, Database db) { String[] cols = Database.ATTCOLS; String[] args = { key }; Cursor cur = db.query("attachments", cols, "attachment_key=?", args, null, null, null, null); Attachment a = load(cur); if (cur != null) cur.close(); return a; } /** * Provides ArrayList of Attachments for a given Item * Useful for powering UI * * We can also use this to trigger background syncs * * @param item * @return */ public static ArrayList<Attachment> forItem(Item item, Database db) { ArrayList<Attachment> list = new ArrayList<Attachment>(); if (item.dbId == null) item.save(db); Log.d(TAG, "Looking for the kids of an item with key: "+item.getKey()); String[] cols = { "_id", "attachment_key", "item_key", "title", "filename", "url", "status", "etag", "dirty", "content" }; String[] args = { item.getKey() }; Cursor cursor = db.query("attachments", cols, "item_key=?", args, null, null, null, null); if (cursor != null) { cursor.moveToFirst(); while (!cursor.isAfterLast()) { Attachment a = Attachment.load(cursor); list.add(a); cursor.moveToNext(); } cursor.close(); } else { Log.d(TAG,"Cursor was null, so we still didn't get attachments for the item!"); } return list; } }