<html> <head> <title>GTaskManager.java</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <style type="text/css"> .s0 { color: #8c8c8c; font-style: italic;} .s1 { color: #080808;} .s2 { color: #0033b3;} .s3 { color: #1750eb;} .s4 { color: #067d17;} </style> </head> <body bgcolor="#ffffff"> <table CELLSPACING=0 CELLPADDING=5 COLS=1 WIDTH="100%" BGCOLOR="#c0c0c0" > <tr><td><center> <font face="Arial, Helvetica" color="#000000"> GTaskManager.java</font> </center></td></tr></table> <pre><span class="s0">/* * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) * * 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. */</span> <span class="s2">package </span><span class="s1">net.micode.notes.gtask.remote;</span> <span class="s2">import </span><span class="s1">android.app.Activity;</span> <span class="s2">import </span><span class="s1">android.content.ContentResolver;</span> <span class="s2">import </span><span class="s1">android.content.ContentUris;</span> <span class="s2">import </span><span class="s1">android.content.ContentValues;</span> <span class="s2">import </span><span class="s1">android.content.Context;</span> <span class="s2">import </span><span class="s1">android.database.Cursor;</span> <span class="s2">import </span><span class="s1">android.util.Log;</span> <span class="s2">import </span><span class="s1">net.micode.notes.R;</span> <span class="s2">import </span><span class="s1">net.micode.notes.data.Notes;</span> <span class="s2">import </span><span class="s1">net.micode.notes.data.Notes.DataColumns;</span> <span class="s2">import </span><span class="s1">net.micode.notes.data.Notes.NoteColumns;</span> <span class="s2">import </span><span class="s1">net.micode.notes.gtask.data.MetaData;</span> <span class="s2">import </span><span class="s1">net.micode.notes.gtask.data.Node;</span> <span class="s2">import </span><span class="s1">net.micode.notes.gtask.data.SqlNote;</span> <span class="s2">import </span><span class="s1">net.micode.notes.gtask.data.Task;</span> <span class="s2">import </span><span class="s1">net.micode.notes.gtask.data.TaskList;</span> <span class="s2">import </span><span class="s1">net.micode.notes.gtask.exception.ActionFailureException;</span> <span class="s2">import </span><span class="s1">net.micode.notes.gtask.exception.NetworkFailureException;</span> <span class="s2">import </span><span class="s1">net.micode.notes.tool.DataUtils;</span> <span class="s2">import </span><span class="s1">net.micode.notes.tool.GTaskStringUtils;</span> <span class="s2">import </span><span class="s1">org.json.JSONArray;</span> <span class="s2">import </span><span class="s1">org.json.JSONException;</span> <span class="s2">import </span><span class="s1">org.json.JSONObject;</span> <span class="s2">import </span><span class="s1">java.util.HashMap;</span> <span class="s2">import </span><span class="s1">java.util.HashSet;</span> <span class="s2">import </span><span class="s1">java.util.Iterator;</span> <span class="s2">import </span><span class="s1">java.util.Map;</span> <span class="s2">public class </span><span class="s1">GTaskManager {</span> <span class="s2">private static final </span><span class="s1">String TAG = GTaskManager.</span><span class="s2">class</span><span class="s1">.getSimpleName();</span> <span class="s2">public static final int </span><span class="s1">STATE_SUCCESS = </span><span class="s3">0</span><span class="s1">;</span> <span class="s2">public static final int </span><span class="s1">STATE_NETWORK_ERROR = </span><span class="s3">1</span><span class="s1">;</span> <span class="s2">public static final int </span><span class="s1">STATE_INTERNAL_ERROR = </span><span class="s3">2</span><span class="s1">;</span> <span class="s2">public static final int </span><span class="s1">STATE_SYNC_IN_PROGRESS = </span><span class="s3">3</span><span class="s1">;</span> <span class="s2">public static final int </span><span class="s1">STATE_SYNC_CANCELLED = </span><span class="s3">4</span><span class="s1">;</span> <span class="s2">private static </span><span class="s1">GTaskManager mInstance = </span><span class="s2">null</span><span class="s1">;</span> <span class="s2">private </span><span class="s1">Activity mActivity;</span> <span class="s2">private </span><span class="s1">Context mContext;</span> <span class="s2">private </span><span class="s1">ContentResolver mContentResolver;</span> <span class="s2">private boolean </span><span class="s1">mSyncing;</span> <span class="s2">private boolean </span><span class="s1">mCancelled;</span> <span class="s2">private </span><span class="s1">HashMap<String, TaskList> mGTaskListHashMap;</span> <span class="s2">private </span><span class="s1">HashMap<String, Node> mGTaskHashMap;</span> <span class="s2">private </span><span class="s1">HashMap<String, MetaData> mMetaHashMap;</span> <span class="s2">private </span><span class="s1">TaskList mMetaList;</span> <span class="s2">private </span><span class="s1">HashSet<Long> mLocalDeleteIdMap;</span> <span class="s2">private </span><span class="s1">HashMap<String, Long> mGidToNid;</span> <span class="s2">private </span><span class="s1">HashMap<Long, String> mNidToGid;</span> <span class="s2">private </span><span class="s1">GTaskManager() {</span> <span class="s1">mSyncing = </span><span class="s2">false</span><span class="s1">;</span> <span class="s1">mCancelled = </span><span class="s2">false</span><span class="s1">;</span> <span class="s1">mGTaskListHashMap = </span><span class="s2">new </span><span class="s1">HashMap<String, TaskList>();</span> <span class="s1">mGTaskHashMap = </span><span class="s2">new </span><span class="s1">HashMap<String, Node>();</span> <span class="s1">mMetaHashMap = </span><span class="s2">new </span><span class="s1">HashMap<String, MetaData>();</span> <span class="s1">mMetaList = </span><span class="s2">null</span><span class="s1">;</span> <span class="s1">mLocalDeleteIdMap = </span><span class="s2">new </span><span class="s1">HashSet<Long>();</span> <span class="s1">mGidToNid = </span><span class="s2">new </span><span class="s1">HashMap<String, Long>();</span> <span class="s1">mNidToGid = </span><span class="s2">new </span><span class="s1">HashMap<Long, String>();</span> <span class="s1">}</span> <span class="s2">public static synchronized </span><span class="s1">GTaskManager getInstance() {</span> <span class="s2">if </span><span class="s1">(mInstance == </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">mInstance = </span><span class="s2">new </span><span class="s1">GTaskManager();</span> <span class="s1">}</span> <span class="s2">return </span><span class="s1">mInstance;</span> <span class="s1">}</span> <span class="s2">public synchronized void </span><span class="s1">setActivityContext(Activity activity) {</span> <span class="s0">// used for getting authtoken</span> <span class="s1">mActivity = activity;</span> <span class="s1">}</span> <span class="s2">public int </span><span class="s1">sync(Context context, GTaskASyncTask asyncTask) {</span> <span class="s2">if </span><span class="s1">(mSyncing) {</span> <span class="s1">Log.d(TAG, </span><span class="s4">"Sync is in progress"</span><span class="s1">);</span> <span class="s2">return </span><span class="s1">STATE_SYNC_IN_PROGRESS;</span> <span class="s1">}</span> <span class="s1">mContext = context;</span> <span class="s1">mContentResolver = mContext.getContentResolver();</span> <span class="s1">mSyncing = </span><span class="s2">true</span><span class="s1">;</span> <span class="s1">mCancelled = </span><span class="s2">false</span><span class="s1">;</span> <span class="s1">mGTaskListHashMap.clear();</span> <span class="s1">mGTaskHashMap.clear();</span> <span class="s1">mMetaHashMap.clear();</span> <span class="s1">mLocalDeleteIdMap.clear();</span> <span class="s1">mGidToNid.clear();</span> <span class="s1">mNidToGid.clear();</span> <span class="s2">try </span><span class="s1">{</span> <span class="s1">GTaskClient client = GTaskClient.getInstance();</span> <span class="s1">client.resetUpdateArray();</span> <span class="s0">// login google task</span> <span class="s2">if </span><span class="s1">(!mCancelled) {</span> <span class="s2">if </span><span class="s1">(!client.login(mActivity)) {</span> <span class="s2">throw new </span><span class="s1">NetworkFailureException(</span><span class="s4">"login google task failed"</span><span class="s1">);</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s0">// get the task list from google</span> <span class="s1">asyncTask.publishProgess(mContext.getString(R.string.sync_progress_init_list));</span> <span class="s1">initGTaskList();</span> <span class="s0">// do content sync work</span> <span class="s1">asyncTask.publishProgess(mContext.getString(R.string.sync_progress_syncing));</span> <span class="s1">syncContent();</span> <span class="s1">} </span><span class="s2">catch </span><span class="s1">(NetworkFailureException e) {</span> <span class="s1">Log.e(TAG, e.toString());</span> <span class="s2">return </span><span class="s1">STATE_NETWORK_ERROR;</span> <span class="s1">} </span><span class="s2">catch </span><span class="s1">(ActionFailureException e) {</span> <span class="s1">Log.e(TAG, e.toString());</span> <span class="s2">return </span><span class="s1">STATE_INTERNAL_ERROR;</span> <span class="s1">} </span><span class="s2">catch </span><span class="s1">(Exception e) {</span> <span class="s1">Log.e(TAG, e.toString());</span> <span class="s1">e.printStackTrace();</span> <span class="s2">return </span><span class="s1">STATE_INTERNAL_ERROR;</span> <span class="s1">} </span><span class="s2">finally </span><span class="s1">{</span> <span class="s1">mGTaskListHashMap.clear();</span> <span class="s1">mGTaskHashMap.clear();</span> <span class="s1">mMetaHashMap.clear();</span> <span class="s1">mLocalDeleteIdMap.clear();</span> <span class="s1">mGidToNid.clear();</span> <span class="s1">mNidToGid.clear();</span> <span class="s1">mSyncing = </span><span class="s2">false</span><span class="s1">;</span> <span class="s1">}</span> <span class="s2">return </span><span class="s1">mCancelled ? STATE_SYNC_CANCELLED : STATE_SUCCESS;</span> <span class="s1">}</span> <span class="s2">private void </span><span class="s1">initGTaskList() </span><span class="s2">throws </span><span class="s1">NetworkFailureException {</span> <span class="s2">if </span><span class="s1">(mCancelled)</span> <span class="s2">return</span><span class="s1">;</span> <span class="s1">GTaskClient client = GTaskClient.getInstance();</span> <span class="s2">try </span><span class="s1">{</span> <span class="s1">JSONArray jsTaskLists = client.getTaskLists();</span> <span class="s0">// init meta list first</span> <span class="s1">mMetaList = </span><span class="s2">null</span><span class="s1">;</span> <span class="s2">for </span><span class="s1">(</span><span class="s2">int </span><span class="s1">i = </span><span class="s3">0</span><span class="s1">; i < jsTaskLists.length(); i++) {</span> <span class="s1">JSONObject object = jsTaskLists.getJSONObject(i);</span> <span class="s1">String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID);</span> <span class="s1">String name = object.getString(GTaskStringUtils.GTASK_JSON_NAME);</span> <span class="s2">if </span><span class="s1">(name</span> <span class="s1">.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META)) {</span> <span class="s1">mMetaList = </span><span class="s2">new </span><span class="s1">TaskList();</span> <span class="s1">mMetaList.setContentByRemoteJSON(object);</span> <span class="s0">// load meta data</span> <span class="s1">JSONArray jsMetas = client.getTaskList(gid);</span> <span class="s2">for </span><span class="s1">(</span><span class="s2">int </span><span class="s1">j = </span><span class="s3">0</span><span class="s1">; j < jsMetas.length(); j++) {</span> <span class="s1">object = (JSONObject) jsMetas.getJSONObject(j);</span> <span class="s1">MetaData metaData = </span><span class="s2">new </span><span class="s1">MetaData();</span> <span class="s1">metaData.setContentByRemoteJSON(object);</span> <span class="s2">if </span><span class="s1">(metaData.isWorthSaving()) {</span> <span class="s1">mMetaList.addChildTask(metaData);</span> <span class="s2">if </span><span class="s1">(metaData.getGid() != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">mMetaHashMap.put(metaData.getRelatedGid(), metaData);</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s0">// create meta list if not existed</span> <span class="s2">if </span><span class="s1">(mMetaList == </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">mMetaList = </span><span class="s2">new </span><span class="s1">TaskList();</span> <span class="s1">mMetaList.setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX</span> <span class="s1">+ GTaskStringUtils.FOLDER_META);</span> <span class="s1">GTaskClient.getInstance().createTaskList(mMetaList);</span> <span class="s1">}</span> <span class="s0">// init task list</span> <span class="s2">for </span><span class="s1">(</span><span class="s2">int </span><span class="s1">i = </span><span class="s3">0</span><span class="s1">; i < jsTaskLists.length(); i++) {</span> <span class="s1">JSONObject object = jsTaskLists.getJSONObject(i);</span> <span class="s1">String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID);</span> <span class="s1">String name = object.getString(GTaskStringUtils.GTASK_JSON_NAME);</span> <span class="s2">if </span><span class="s1">(name.startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX)</span> <span class="s1">&& !name.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX</span> <span class="s1">+ GTaskStringUtils.FOLDER_META)) {</span> <span class="s1">TaskList tasklist = </span><span class="s2">new </span><span class="s1">TaskList();</span> <span class="s1">tasklist.setContentByRemoteJSON(object);</span> <span class="s1">mGTaskListHashMap.put(gid, tasklist);</span> <span class="s1">mGTaskHashMap.put(gid, tasklist);</span> <span class="s0">// load tasks</span> <span class="s1">JSONArray jsTasks = client.getTaskList(gid);</span> <span class="s2">for </span><span class="s1">(</span><span class="s2">int </span><span class="s1">j = </span><span class="s3">0</span><span class="s1">; j < jsTasks.length(); j++) {</span> <span class="s1">object = (JSONObject) jsTasks.getJSONObject(j);</span> <span class="s1">gid = object.getString(GTaskStringUtils.GTASK_JSON_ID);</span> <span class="s1">Task task = </span><span class="s2">new </span><span class="s1">Task();</span> <span class="s1">task.setContentByRemoteJSON(object);</span> <span class="s2">if </span><span class="s1">(task.isWorthSaving()) {</span> <span class="s1">task.setMetaInfo(mMetaHashMap.get(gid));</span> <span class="s1">tasklist.addChildTask(task);</span> <span class="s1">mGTaskHashMap.put(gid, task);</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s1">} </span><span class="s2">catch </span><span class="s1">(JSONException e) {</span> <span class="s1">Log.e(TAG, e.toString());</span> <span class="s1">e.printStackTrace();</span> <span class="s2">throw new </span><span class="s1">ActionFailureException(</span><span class="s4">"initGTaskList: handing JSONObject failed"</span><span class="s1">);</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s2">private void </span><span class="s1">syncContent() </span><span class="s2">throws </span><span class="s1">NetworkFailureException {</span> <span class="s2">int </span><span class="s1">syncType;</span> <span class="s1">Cursor c = </span><span class="s2">null</span><span class="s1">;</span> <span class="s1">String gid;</span> <span class="s1">Node node;</span> <span class="s1">mLocalDeleteIdMap.clear();</span> <span class="s2">if </span><span class="s1">(mCancelled) {</span> <span class="s2">return</span><span class="s1">;</span> <span class="s1">}</span> <span class="s0">// for local deleted note</span> <span class="s2">try </span><span class="s1">{</span> <span class="s1">c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE,</span> <span class="s4">"(type<>? AND parent_id=?)"</span><span class="s1">, </span><span class="s2">new </span><span class="s1">String[] {</span> <span class="s1">String.valueOf(Notes.TYPE_SYSTEM), String.valueOf(Notes.ID_TRASH_FOLER)</span> <span class="s1">}, </span><span class="s2">null</span><span class="s1">);</span> <span class="s2">if </span><span class="s1">(c != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s2">while </span><span class="s1">(c.moveToNext()) {</span> <span class="s1">gid = c.getString(SqlNote.GTASK_ID_COLUMN);</span> <span class="s1">node = mGTaskHashMap.get(gid);</span> <span class="s2">if </span><span class="s1">(node != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">mGTaskHashMap.remove(gid);</span> <span class="s1">doContentSync(Node.SYNC_ACTION_DEL_REMOTE, node, c);</span> <span class="s1">}</span> <span class="s1">mLocalDeleteIdMap.add(c.getLong(SqlNote.ID_COLUMN));</span> <span class="s1">}</span> <span class="s1">} </span><span class="s2">else </span><span class="s1">{</span> <span class="s1">Log.w(TAG, </span><span class="s4">"failed to query trash folder"</span><span class="s1">);</span> <span class="s1">}</span> <span class="s1">} </span><span class="s2">finally </span><span class="s1">{</span> <span class="s2">if </span><span class="s1">(c != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">c.close();</span> <span class="s1">c = </span><span class="s2">null</span><span class="s1">;</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s0">// sync folder first</span> <span class="s1">syncFolder();</span> <span class="s0">// for note existing in database</span> <span class="s2">try </span><span class="s1">{</span> <span class="s1">c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE,</span> <span class="s4">"(type=? AND parent_id<>?)"</span><span class="s1">, </span><span class="s2">new </span><span class="s1">String[] {</span> <span class="s1">String.valueOf(Notes.TYPE_NOTE), String.valueOf(Notes.ID_TRASH_FOLER)</span> <span class="s1">}, NoteColumns.TYPE + </span><span class="s4">" DESC"</span><span class="s1">);</span> <span class="s2">if </span><span class="s1">(c != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s2">while </span><span class="s1">(c.moveToNext()) {</span> <span class="s1">gid = c.getString(SqlNote.GTASK_ID_COLUMN);</span> <span class="s1">node = mGTaskHashMap.get(gid);</span> <span class="s2">if </span><span class="s1">(node != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">mGTaskHashMap.remove(gid);</span> <span class="s1">mGidToNid.put(gid, c.getLong(SqlNote.ID_COLUMN));</span> <span class="s1">mNidToGid.put(c.getLong(SqlNote.ID_COLUMN), gid);</span> <span class="s1">syncType = node.getSyncAction(c);</span> <span class="s1">} </span><span class="s2">else </span><span class="s1">{</span> <span class="s2">if </span><span class="s1">(c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == </span><span class="s3">0</span><span class="s1">) {</span> <span class="s0">// local add</span> <span class="s1">syncType = Node.SYNC_ACTION_ADD_REMOTE;</span> <span class="s1">} </span><span class="s2">else </span><span class="s1">{</span> <span class="s0">// remote delete</span> <span class="s1">syncType = Node.SYNC_ACTION_DEL_LOCAL;</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s1">doContentSync(syncType, node, c);</span> <span class="s1">}</span> <span class="s1">} </span><span class="s2">else </span><span class="s1">{</span> <span class="s1">Log.w(TAG, </span><span class="s4">"failed to query existing note in database"</span><span class="s1">);</span> <span class="s1">}</span> <span class="s1">} </span><span class="s2">finally </span><span class="s1">{</span> <span class="s2">if </span><span class="s1">(c != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">c.close();</span> <span class="s1">c = </span><span class="s2">null</span><span class="s1">;</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s0">// go through remaining items</span> <span class="s1">Iterator<Map.Entry<String, Node>> iter = mGTaskHashMap.entrySet().iterator();</span> <span class="s2">while </span><span class="s1">(iter.hasNext()) {</span> <span class="s1">Map.Entry<String, Node> entry = iter.next();</span> <span class="s1">node = entry.getValue();</span> <span class="s1">doContentSync(Node.SYNC_ACTION_ADD_LOCAL, node, </span><span class="s2">null</span><span class="s1">);</span> <span class="s1">}</span> <span class="s0">// mCancelled can be set by another thread, so we neet to check one by</span> <span class="s0">// one</span> <span class="s0">// clear local delete table</span> <span class="s2">if </span><span class="s1">(!mCancelled) {</span> <span class="s2">if </span><span class="s1">(!DataUtils.batchDeleteNotes(mContentResolver, mLocalDeleteIdMap)) {</span> <span class="s2">throw new </span><span class="s1">ActionFailureException(</span><span class="s4">"failed to batch-delete local deleted notes"</span><span class="s1">);</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s0">// refresh local sync id</span> <span class="s2">if </span><span class="s1">(!mCancelled) {</span> <span class="s1">GTaskClient.getInstance().commitUpdate();</span> <span class="s1">refreshLocalSyncId();</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s2">private void </span><span class="s1">syncFolder() </span><span class="s2">throws </span><span class="s1">NetworkFailureException {</span> <span class="s1">Cursor c = </span><span class="s2">null</span><span class="s1">;</span> <span class="s1">String gid;</span> <span class="s1">Node node;</span> <span class="s2">int </span><span class="s1">syncType;</span> <span class="s2">if </span><span class="s1">(mCancelled) {</span> <span class="s2">return</span><span class="s1">;</span> <span class="s1">}</span> <span class="s0">// for root folder</span> <span class="s2">try </span><span class="s1">{</span> <span class="s1">c = mContentResolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI,</span> <span class="s1">Notes.ID_ROOT_FOLDER), SqlNote.PROJECTION_NOTE, </span><span class="s2">null</span><span class="s1">, </span><span class="s2">null</span><span class="s1">, </span><span class="s2">null</span><span class="s1">);</span> <span class="s2">if </span><span class="s1">(c != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">c.moveToNext();</span> <span class="s1">gid = c.getString(SqlNote.GTASK_ID_COLUMN);</span> <span class="s1">node = mGTaskHashMap.get(gid);</span> <span class="s2">if </span><span class="s1">(node != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">mGTaskHashMap.remove(gid);</span> <span class="s1">mGidToNid.put(gid, (</span><span class="s2">long</span><span class="s1">) Notes.ID_ROOT_FOLDER);</span> <span class="s1">mNidToGid.put((</span><span class="s2">long</span><span class="s1">) Notes.ID_ROOT_FOLDER, gid);</span> <span class="s0">// for system folder, only update remote name if necessary</span> <span class="s2">if </span><span class="s1">(!node.getName().equals(</span> <span class="s1">GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT))</span> <span class="s1">doContentSync(Node.SYNC_ACTION_UPDATE_REMOTE, node, c);</span> <span class="s1">} </span><span class="s2">else </span><span class="s1">{</span> <span class="s1">doContentSync(Node.SYNC_ACTION_ADD_REMOTE, node, c);</span> <span class="s1">}</span> <span class="s1">} </span><span class="s2">else </span><span class="s1">{</span> <span class="s1">Log.w(TAG, </span><span class="s4">"failed to query root folder"</span><span class="s1">);</span> <span class="s1">}</span> <span class="s1">} </span><span class="s2">finally </span><span class="s1">{</span> <span class="s2">if </span><span class="s1">(c != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">c.close();</span> <span class="s1">c = </span><span class="s2">null</span><span class="s1">;</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s0">// for call-note folder</span> <span class="s2">try </span><span class="s1">{</span> <span class="s1">c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, </span><span class="s4">"(_id=?)"</span><span class="s1">,</span> <span class="s2">new </span><span class="s1">String[] {</span> <span class="s1">String.valueOf(Notes.ID_CALL_RECORD_FOLDER)</span> <span class="s1">}, </span><span class="s2">null</span><span class="s1">);</span> <span class="s2">if </span><span class="s1">(c != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s2">if </span><span class="s1">(c.moveToNext()) {</span> <span class="s1">gid = c.getString(SqlNote.GTASK_ID_COLUMN);</span> <span class="s1">node = mGTaskHashMap.get(gid);</span> <span class="s2">if </span><span class="s1">(node != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">mGTaskHashMap.remove(gid);</span> <span class="s1">mGidToNid.put(gid, (</span><span class="s2">long</span><span class="s1">) Notes.ID_CALL_RECORD_FOLDER);</span> <span class="s1">mNidToGid.put((</span><span class="s2">long</span><span class="s1">) Notes.ID_CALL_RECORD_FOLDER, gid);</span> <span class="s0">// for system folder, only update remote name if</span> <span class="s0">// necessary</span> <span class="s2">if </span><span class="s1">(!node.getName().equals(</span> <span class="s1">GTaskStringUtils.MIUI_FOLDER_PREFFIX</span> <span class="s1">+ GTaskStringUtils.FOLDER_CALL_NOTE))</span> <span class="s1">doContentSync(Node.SYNC_ACTION_UPDATE_REMOTE, node, c);</span> <span class="s1">} </span><span class="s2">else </span><span class="s1">{</span> <span class="s1">doContentSync(Node.SYNC_ACTION_ADD_REMOTE, node, c);</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s1">} </span><span class="s2">else </span><span class="s1">{</span> <span class="s1">Log.w(TAG, </span><span class="s4">"failed to query call note folder"</span><span class="s1">);</span> <span class="s1">}</span> <span class="s1">} </span><span class="s2">finally </span><span class="s1">{</span> <span class="s2">if </span><span class="s1">(c != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">c.close();</span> <span class="s1">c = </span><span class="s2">null</span><span class="s1">;</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s0">// for local existing folders</span> <span class="s2">try </span><span class="s1">{</span> <span class="s1">c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE,</span> <span class="s4">"(type=? AND parent_id<>?)"</span><span class="s1">, </span><span class="s2">new </span><span class="s1">String[] {</span> <span class="s1">String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER)</span> <span class="s1">}, NoteColumns.TYPE + </span><span class="s4">" DESC"</span><span class="s1">);</span> <span class="s2">if </span><span class="s1">(c != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s2">while </span><span class="s1">(c.moveToNext()) {</span> <span class="s1">gid = c.getString(SqlNote.GTASK_ID_COLUMN);</span> <span class="s1">node = mGTaskHashMap.get(gid);</span> <span class="s2">if </span><span class="s1">(node != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">mGTaskHashMap.remove(gid);</span> <span class="s1">mGidToNid.put(gid, c.getLong(SqlNote.ID_COLUMN));</span> <span class="s1">mNidToGid.put(c.getLong(SqlNote.ID_COLUMN), gid);</span> <span class="s1">syncType = node.getSyncAction(c);</span> <span class="s1">} </span><span class="s2">else </span><span class="s1">{</span> <span class="s2">if </span><span class="s1">(c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == </span><span class="s3">0</span><span class="s1">) {</span> <span class="s0">// local add</span> <span class="s1">syncType = Node.SYNC_ACTION_ADD_REMOTE;</span> <span class="s1">} </span><span class="s2">else </span><span class="s1">{</span> <span class="s0">// remote delete</span> <span class="s1">syncType = Node.SYNC_ACTION_DEL_LOCAL;</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s1">doContentSync(syncType, node, c);</span> <span class="s1">}</span> <span class="s1">} </span><span class="s2">else </span><span class="s1">{</span> <span class="s1">Log.w(TAG, </span><span class="s4">"failed to query existing folder"</span><span class="s1">);</span> <span class="s1">}</span> <span class="s1">} </span><span class="s2">finally </span><span class="s1">{</span> <span class="s2">if </span><span class="s1">(c != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">c.close();</span> <span class="s1">c = </span><span class="s2">null</span><span class="s1">;</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s0">// for remote add folders</span> <span class="s1">Iterator<Map.Entry<String, TaskList>> iter = mGTaskListHashMap.entrySet().iterator();</span> <span class="s2">while </span><span class="s1">(iter.hasNext()) {</span> <span class="s1">Map.Entry<String, TaskList> entry = iter.next();</span> <span class="s1">gid = entry.getKey();</span> <span class="s1">node = entry.getValue();</span> <span class="s2">if </span><span class="s1">(mGTaskHashMap.containsKey(gid)) {</span> <span class="s1">mGTaskHashMap.remove(gid);</span> <span class="s1">doContentSync(Node.SYNC_ACTION_ADD_LOCAL, node, </span><span class="s2">null</span><span class="s1">);</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s2">if </span><span class="s1">(!mCancelled)</span> <span class="s1">GTaskClient.getInstance().commitUpdate();</span> <span class="s1">}</span> <span class="s2">private void </span><span class="s1">doContentSync(</span><span class="s2">int </span><span class="s1">syncType, Node node, Cursor c) </span><span class="s2">throws </span><span class="s1">NetworkFailureException {</span> <span class="s2">if </span><span class="s1">(mCancelled) {</span> <span class="s2">return</span><span class="s1">;</span> <span class="s1">}</span> <span class="s1">MetaData meta;</span> <span class="s2">switch </span><span class="s1">(syncType) {</span> <span class="s2">case </span><span class="s1">Node.SYNC_ACTION_ADD_LOCAL:</span> <span class="s1">addLocalNode(node);</span> <span class="s2">break</span><span class="s1">;</span> <span class="s2">case </span><span class="s1">Node.SYNC_ACTION_ADD_REMOTE:</span> <span class="s1">addRemoteNode(node, c);</span> <span class="s2">break</span><span class="s1">;</span> <span class="s2">case </span><span class="s1">Node.SYNC_ACTION_DEL_LOCAL:</span> <span class="s1">meta = mMetaHashMap.get(c.getString(SqlNote.GTASK_ID_COLUMN));</span> <span class="s2">if </span><span class="s1">(meta != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">GTaskClient.getInstance().deleteNode(meta);</span> <span class="s1">}</span> <span class="s1">mLocalDeleteIdMap.add(c.getLong(SqlNote.ID_COLUMN));</span> <span class="s2">break</span><span class="s1">;</span> <span class="s2">case </span><span class="s1">Node.SYNC_ACTION_DEL_REMOTE:</span> <span class="s1">meta = mMetaHashMap.get(node.getGid());</span> <span class="s2">if </span><span class="s1">(meta != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">GTaskClient.getInstance().deleteNode(meta);</span> <span class="s1">}</span> <span class="s1">GTaskClient.getInstance().deleteNode(node);</span> <span class="s2">break</span><span class="s1">;</span> <span class="s2">case </span><span class="s1">Node.SYNC_ACTION_UPDATE_LOCAL:</span> <span class="s1">updateLocalNode(node, c);</span> <span class="s2">break</span><span class="s1">;</span> <span class="s2">case </span><span class="s1">Node.SYNC_ACTION_UPDATE_REMOTE:</span> <span class="s1">updateRemoteNode(node, c);</span> <span class="s2">break</span><span class="s1">;</span> <span class="s2">case </span><span class="s1">Node.SYNC_ACTION_UPDATE_CONFLICT:</span> <span class="s0">// merging both modifications maybe a good idea</span> <span class="s0">// right now just use local update simply</span> <span class="s1">updateRemoteNode(node, c);</span> <span class="s2">break</span><span class="s1">;</span> <span class="s2">case </span><span class="s1">Node.SYNC_ACTION_NONE:</span> <span class="s2">break</span><span class="s1">;</span> <span class="s2">case </span><span class="s1">Node.SYNC_ACTION_ERROR:</span> <span class="s2">default</span><span class="s1">:</span> <span class="s2">throw new </span><span class="s1">ActionFailureException(</span><span class="s4">"unkown sync action type"</span><span class="s1">);</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s2">private void </span><span class="s1">addLocalNode(Node node) </span><span class="s2">throws </span><span class="s1">NetworkFailureException {</span> <span class="s2">if </span><span class="s1">(mCancelled) {</span> <span class="s2">return</span><span class="s1">;</span> <span class="s1">}</span> <span class="s1">SqlNote sqlNote;</span> <span class="s2">if </span><span class="s1">(node </span><span class="s2">instanceof </span><span class="s1">TaskList) {</span> <span class="s2">if </span><span class="s1">(node.getName().equals(</span> <span class="s1">GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT)) {</span> <span class="s1">sqlNote = </span><span class="s2">new </span><span class="s1">SqlNote(mContext, Notes.ID_ROOT_FOLDER);</span> <span class="s1">} </span><span class="s2">else if </span><span class="s1">(node.getName().equals(</span> <span class="s1">GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_CALL_NOTE)) {</span> <span class="s1">sqlNote = </span><span class="s2">new </span><span class="s1">SqlNote(mContext, Notes.ID_CALL_RECORD_FOLDER);</span> <span class="s1">} </span><span class="s2">else </span><span class="s1">{</span> <span class="s1">sqlNote = </span><span class="s2">new </span><span class="s1">SqlNote(mContext);</span> <span class="s1">sqlNote.setContent(node.getLocalJSONFromContent());</span> <span class="s1">sqlNote.setParentId(Notes.ID_ROOT_FOLDER);</span> <span class="s1">}</span> <span class="s1">} </span><span class="s2">else </span><span class="s1">{</span> <span class="s1">sqlNote = </span><span class="s2">new </span><span class="s1">SqlNote(mContext);</span> <span class="s1">JSONObject js = node.getLocalJSONFromContent();</span> <span class="s2">try </span><span class="s1">{</span> <span class="s2">if </span><span class="s1">(js.has(GTaskStringUtils.META_HEAD_NOTE)) {</span> <span class="s1">JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);</span> <span class="s2">if </span><span class="s1">(note.has(NoteColumns.ID)) {</span> <span class="s2">long </span><span class="s1">id = note.getLong(NoteColumns.ID);</span> <span class="s2">if </span><span class="s1">(DataUtils.existInNoteDatabase(mContentResolver, id)) {</span> <span class="s0">// the id is not available, have to create a new one</span> <span class="s1">note.remove(NoteColumns.ID);</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s2">if </span><span class="s1">(js.has(GTaskStringUtils.META_HEAD_DATA)) {</span> <span class="s1">JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);</span> <span class="s2">for </span><span class="s1">(</span><span class="s2">int </span><span class="s1">i = </span><span class="s3">0</span><span class="s1">; i < dataArray.length(); i++) {</span> <span class="s1">JSONObject data = dataArray.getJSONObject(i);</span> <span class="s2">if </span><span class="s1">(data.has(DataColumns.ID)) {</span> <span class="s2">long </span><span class="s1">dataId = data.getLong(DataColumns.ID);</span> <span class="s2">if </span><span class="s1">(DataUtils.existInDataDatabase(mContentResolver, dataId)) {</span> <span class="s0">// the data id is not available, have to create</span> <span class="s0">// a new one</span> <span class="s1">data.remove(DataColumns.ID);</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s1">} </span><span class="s2">catch </span><span class="s1">(JSONException e) {</span> <span class="s1">Log.w(TAG, e.toString());</span> <span class="s1">e.printStackTrace();</span> <span class="s1">}</span> <span class="s1">sqlNote.setContent(js);</span> <span class="s1">Long parentId = mGidToNid.get(((Task) node).getParent().getGid());</span> <span class="s2">if </span><span class="s1">(parentId == </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">Log.e(TAG, </span><span class="s4">"cannot find task's parent id locally"</span><span class="s1">);</span> <span class="s2">throw new </span><span class="s1">ActionFailureException(</span><span class="s4">"cannot add local node"</span><span class="s1">);</span> <span class="s1">}</span> <span class="s1">sqlNote.setParentId(parentId.longValue());</span> <span class="s1">}</span> <span class="s0">// create the local node</span> <span class="s1">sqlNote.setGtaskId(node.getGid());</span> <span class="s1">sqlNote.commit(</span><span class="s2">false</span><span class="s1">);</span> <span class="s0">// update gid-nid mapping</span> <span class="s1">mGidToNid.put(node.getGid(), sqlNote.getId());</span> <span class="s1">mNidToGid.put(sqlNote.getId(), node.getGid());</span> <span class="s0">// update meta</span> <span class="s1">updateRemoteMeta(node.getGid(), sqlNote);</span> <span class="s1">}</span> <span class="s2">private void </span><span class="s1">updateLocalNode(Node node, Cursor c) </span><span class="s2">throws </span><span class="s1">NetworkFailureException {</span> <span class="s2">if </span><span class="s1">(mCancelled) {</span> <span class="s2">return</span><span class="s1">;</span> <span class="s1">}</span> <span class="s1">SqlNote sqlNote;</span> <span class="s0">// update the note locally</span> <span class="s1">sqlNote = </span><span class="s2">new </span><span class="s1">SqlNote(mContext, c);</span> <span class="s1">sqlNote.setContent(node.getLocalJSONFromContent());</span> <span class="s1">Long parentId = (node </span><span class="s2">instanceof </span><span class="s1">Task) ? mGidToNid.get(((Task) node).getParent().getGid())</span> <span class="s1">: </span><span class="s2">new </span><span class="s1">Long(Notes.ID_ROOT_FOLDER);</span> <span class="s2">if </span><span class="s1">(parentId == </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">Log.e(TAG, </span><span class="s4">"cannot find task's parent id locally"</span><span class="s1">);</span> <span class="s2">throw new </span><span class="s1">ActionFailureException(</span><span class="s4">"cannot update local node"</span><span class="s1">);</span> <span class="s1">}</span> <span class="s1">sqlNote.setParentId(parentId.longValue());</span> <span class="s1">sqlNote.commit(</span><span class="s2">true</span><span class="s1">);</span> <span class="s0">// update meta info</span> <span class="s1">updateRemoteMeta(node.getGid(), sqlNote);</span> <span class="s1">}</span> <span class="s2">private void </span><span class="s1">addRemoteNode(Node node, Cursor c) </span><span class="s2">throws </span><span class="s1">NetworkFailureException {</span> <span class="s2">if </span><span class="s1">(mCancelled) {</span> <span class="s2">return</span><span class="s1">;</span> <span class="s1">}</span> <span class="s1">SqlNote sqlNote = </span><span class="s2">new </span><span class="s1">SqlNote(mContext, c);</span> <span class="s1">Node n;</span> <span class="s0">// update remotely</span> <span class="s2">if </span><span class="s1">(sqlNote.isNoteType()) {</span> <span class="s1">Task task = </span><span class="s2">new </span><span class="s1">Task();</span> <span class="s1">task.setContentByLocalJSON(sqlNote.getContent());</span> <span class="s1">String parentGid = mNidToGid.get(sqlNote.getParentId());</span> <span class="s2">if </span><span class="s1">(parentGid == </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">Log.e(TAG, </span><span class="s4">"cannot find task's parent tasklist"</span><span class="s1">);</span> <span class="s2">throw new </span><span class="s1">ActionFailureException(</span><span class="s4">"cannot add remote task"</span><span class="s1">);</span> <span class="s1">}</span> <span class="s1">mGTaskListHashMap.get(parentGid).addChildTask(task);</span> <span class="s1">GTaskClient.getInstance().createTask(task);</span> <span class="s1">n = (Node) task;</span> <span class="s0">// add meta</span> <span class="s1">updateRemoteMeta(task.getGid(), sqlNote);</span> <span class="s1">} </span><span class="s2">else </span><span class="s1">{</span> <span class="s1">TaskList tasklist = </span><span class="s2">null</span><span class="s1">;</span> <span class="s0">// we need to skip folder if it has already existed</span> <span class="s1">String folderName = GTaskStringUtils.MIUI_FOLDER_PREFFIX;</span> <span class="s2">if </span><span class="s1">(sqlNote.getId() == Notes.ID_ROOT_FOLDER)</span> <span class="s1">folderName += GTaskStringUtils.FOLDER_DEFAULT;</span> <span class="s2">else if </span><span class="s1">(sqlNote.getId() == Notes.ID_CALL_RECORD_FOLDER)</span> <span class="s1">folderName += GTaskStringUtils.FOLDER_CALL_NOTE;</span> <span class="s2">else</span> <span class="s1">folderName += sqlNote.getSnippet();</span> <span class="s1">Iterator<Map.Entry<String, TaskList>> iter = mGTaskListHashMap.entrySet().iterator();</span> <span class="s2">while </span><span class="s1">(iter.hasNext()) {</span> <span class="s1">Map.Entry<String, TaskList> entry = iter.next();</span> <span class="s1">String gid = entry.getKey();</span> <span class="s1">TaskList list = entry.getValue();</span> <span class="s2">if </span><span class="s1">(list.getName().equals(folderName)) {</span> <span class="s1">tasklist = list;</span> <span class="s2">if </span><span class="s1">(mGTaskHashMap.containsKey(gid)) {</span> <span class="s1">mGTaskHashMap.remove(gid);</span> <span class="s1">}</span> <span class="s2">break</span><span class="s1">;</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s0">// no match we can add now</span> <span class="s2">if </span><span class="s1">(tasklist == </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">tasklist = </span><span class="s2">new </span><span class="s1">TaskList();</span> <span class="s1">tasklist.setContentByLocalJSON(sqlNote.getContent());</span> <span class="s1">GTaskClient.getInstance().createTaskList(tasklist);</span> <span class="s1">mGTaskListHashMap.put(tasklist.getGid(), tasklist);</span> <span class="s1">}</span> <span class="s1">n = (Node) tasklist;</span> <span class="s1">}</span> <span class="s0">// update local note</span> <span class="s1">sqlNote.setGtaskId(n.getGid());</span> <span class="s1">sqlNote.commit(</span><span class="s2">false</span><span class="s1">);</span> <span class="s1">sqlNote.resetLocalModified();</span> <span class="s1">sqlNote.commit(</span><span class="s2">true</span><span class="s1">);</span> <span class="s0">// gid-id mapping</span> <span class="s1">mGidToNid.put(n.getGid(), sqlNote.getId());</span> <span class="s1">mNidToGid.put(sqlNote.getId(), n.getGid());</span> <span class="s1">}</span> <span class="s2">private void </span><span class="s1">updateRemoteNode(Node node, Cursor c) </span><span class="s2">throws </span><span class="s1">NetworkFailureException {</span> <span class="s2">if </span><span class="s1">(mCancelled) {</span> <span class="s2">return</span><span class="s1">;</span> <span class="s1">}</span> <span class="s1">SqlNote sqlNote = </span><span class="s2">new </span><span class="s1">SqlNote(mContext, c);</span> <span class="s0">// update remotely</span> <span class="s1">node.setContentByLocalJSON(sqlNote.getContent());</span> <span class="s1">GTaskClient.getInstance().addUpdateNode(node);</span> <span class="s0">// update meta</span> <span class="s1">updateRemoteMeta(node.getGid(), sqlNote);</span> <span class="s0">// move task if necessary</span> <span class="s2">if </span><span class="s1">(sqlNote.isNoteType()) {</span> <span class="s1">Task task = (Task) node;</span> <span class="s1">TaskList preParentList = task.getParent();</span> <span class="s1">String curParentGid = mNidToGid.get(sqlNote.getParentId());</span> <span class="s2">if </span><span class="s1">(curParentGid == </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">Log.e(TAG, </span><span class="s4">"cannot find task's parent tasklist"</span><span class="s1">);</span> <span class="s2">throw new </span><span class="s1">ActionFailureException(</span><span class="s4">"cannot update remote task"</span><span class="s1">);</span> <span class="s1">}</span> <span class="s1">TaskList curParentList = mGTaskListHashMap.get(curParentGid);</span> <span class="s2">if </span><span class="s1">(preParentList != curParentList) {</span> <span class="s1">preParentList.removeChildTask(task);</span> <span class="s1">curParentList.addChildTask(task);</span> <span class="s1">GTaskClient.getInstance().moveTask(task, preParentList, curParentList);</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s0">// clear local modified flag</span> <span class="s1">sqlNote.resetLocalModified();</span> <span class="s1">sqlNote.commit(</span><span class="s2">true</span><span class="s1">);</span> <span class="s1">}</span> <span class="s2">private void </span><span class="s1">updateRemoteMeta(String gid, SqlNote sqlNote) </span><span class="s2">throws </span><span class="s1">NetworkFailureException {</span> <span class="s2">if </span><span class="s1">(sqlNote != </span><span class="s2">null </span><span class="s1">&& sqlNote.isNoteType()) {</span> <span class="s1">MetaData metaData = mMetaHashMap.get(gid);</span> <span class="s2">if </span><span class="s1">(metaData != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">metaData.setMeta(gid, sqlNote.getContent());</span> <span class="s1">GTaskClient.getInstance().addUpdateNode(metaData);</span> <span class="s1">} </span><span class="s2">else </span><span class="s1">{</span> <span class="s1">metaData = </span><span class="s2">new </span><span class="s1">MetaData();</span> <span class="s1">metaData.setMeta(gid, sqlNote.getContent());</span> <span class="s1">mMetaList.addChildTask(metaData);</span> <span class="s1">mMetaHashMap.put(gid, metaData);</span> <span class="s1">GTaskClient.getInstance().createTask(metaData);</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s2">private void </span><span class="s1">refreshLocalSyncId() </span><span class="s2">throws </span><span class="s1">NetworkFailureException {</span> <span class="s2">if </span><span class="s1">(mCancelled) {</span> <span class="s2">return</span><span class="s1">;</span> <span class="s1">}</span> <span class="s0">// get the latest gtask list</span> <span class="s1">mGTaskHashMap.clear();</span> <span class="s1">mGTaskListHashMap.clear();</span> <span class="s1">mMetaHashMap.clear();</span> <span class="s1">initGTaskList();</span> <span class="s1">Cursor c = </span><span class="s2">null</span><span class="s1">;</span> <span class="s2">try </span><span class="s1">{</span> <span class="s1">c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE,</span> <span class="s4">"(type<>? AND parent_id<>?)"</span><span class="s1">, </span><span class="s2">new </span><span class="s1">String[] {</span> <span class="s1">String.valueOf(Notes.TYPE_SYSTEM), String.valueOf(Notes.ID_TRASH_FOLER)</span> <span class="s1">}, NoteColumns.TYPE + </span><span class="s4">" DESC"</span><span class="s1">);</span> <span class="s2">if </span><span class="s1">(c != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s2">while </span><span class="s1">(c.moveToNext()) {</span> <span class="s1">String gid = c.getString(SqlNote.GTASK_ID_COLUMN);</span> <span class="s1">Node node = mGTaskHashMap.get(gid);</span> <span class="s2">if </span><span class="s1">(node != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">mGTaskHashMap.remove(gid);</span> <span class="s1">ContentValues values = </span><span class="s2">new </span><span class="s1">ContentValues();</span> <span class="s1">values.put(NoteColumns.SYNC_ID, node.getLastModified());</span> <span class="s1">mContentResolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI,</span> <span class="s1">c.getLong(SqlNote.ID_COLUMN)), values, </span><span class="s2">null</span><span class="s1">, </span><span class="s2">null</span><span class="s1">);</span> <span class="s1">} </span><span class="s2">else </span><span class="s1">{</span> <span class="s1">Log.e(TAG, </span><span class="s4">"something is missed"</span><span class="s1">);</span> <span class="s2">throw new </span><span class="s1">ActionFailureException(</span> <span class="s4">"some local items don't have gid after sync"</span><span class="s1">);</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s1">} </span><span class="s2">else </span><span class="s1">{</span> <span class="s1">Log.w(TAG, </span><span class="s4">"failed to query local note to refresh sync id"</span><span class="s1">);</span> <span class="s1">}</span> <span class="s1">} </span><span class="s2">finally </span><span class="s1">{</span> <span class="s2">if </span><span class="s1">(c != </span><span class="s2">null</span><span class="s1">) {</span> <span class="s1">c.close();</span> <span class="s1">c = </span><span class="s2">null</span><span class="s1">;</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s1">}</span> <span class="s2">public </span><span class="s1">String getSyncAccount() {</span> <span class="s2">return </span><span class="s1">GTaskClient.getInstance().getSyncAccount().name;</span> <span class="s1">}</span> <span class="s2">public void </span><span class="s1">cancelSync() {</span> <span class="s1">mCancelled = </span><span class="s2">true</span><span class="s1">;</span> <span class="s1">}</span> <span class="s1">}</span> </pre> </body> </html>