You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

821 lines
60 KiB

<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 &quot;License&quot;);
* 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 &quot;AS IS&quot; 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&lt;String, TaskList&gt; mGTaskListHashMap;</span>
<span class="s2">private </span><span class="s1">HashMap&lt;String, Node&gt; mGTaskHashMap;</span>
<span class="s2">private </span><span class="s1">HashMap&lt;String, MetaData&gt; mMetaHashMap;</span>
<span class="s2">private </span><span class="s1">TaskList mMetaList;</span>
<span class="s2">private </span><span class="s1">HashSet&lt;Long&gt; mLocalDeleteIdMap;</span>
<span class="s2">private </span><span class="s1">HashMap&lt;String, Long&gt; mGidToNid;</span>
<span class="s2">private </span><span class="s1">HashMap&lt;Long, String&gt; 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&lt;String, TaskList&gt;();</span>
<span class="s1">mGTaskHashMap = </span><span class="s2">new </span><span class="s1">HashMap&lt;String, Node&gt;();</span>
<span class="s1">mMetaHashMap = </span><span class="s2">new </span><span class="s1">HashMap&lt;String, MetaData&gt;();</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&lt;Long&gt;();</span>
<span class="s1">mGidToNid = </span><span class="s2">new </span><span class="s1">HashMap&lt;String, Long&gt;();</span>
<span class="s1">mNidToGid = </span><span class="s2">new </span><span class="s1">HashMap&lt;Long, String&gt;();</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">&quot;Sync is in progress&quot;</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">&quot;login google task failed&quot;</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 &lt; 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 &lt; 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 &lt; 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">&amp;&amp; !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 &lt; 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">&quot;initGTaskList: handing JSONObject failed&quot;</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">&quot;(type&lt;&gt;? AND parent_id=?)&quot;</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">&quot;failed to query trash folder&quot;</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">&quot;(type=? AND parent_id&lt;&gt;?)&quot;</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">&quot; DESC&quot;</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">&quot;failed to query existing note in database&quot;</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&lt;Map.Entry&lt;String, Node&gt;&gt; iter = mGTaskHashMap.entrySet().iterator();</span>
<span class="s2">while </span><span class="s1">(iter.hasNext()) {</span>
<span class="s1">Map.Entry&lt;String, Node&gt; 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">&quot;failed to batch-delete local deleted notes&quot;</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">&quot;failed to query root folder&quot;</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">&quot;(_id=?)&quot;</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">&quot;failed to query call note folder&quot;</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">&quot;(type=? AND parent_id&lt;&gt;?)&quot;</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">&quot; DESC&quot;</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">&quot;failed to query existing folder&quot;</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&lt;Map.Entry&lt;String, TaskList&gt;&gt; iter = mGTaskListHashMap.entrySet().iterator();</span>
<span class="s2">while </span><span class="s1">(iter.hasNext()) {</span>
<span class="s1">Map.Entry&lt;String, TaskList&gt; 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">&quot;unkown sync action type&quot;</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 &lt; 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">&quot;cannot find task's parent id locally&quot;</span><span class="s1">);</span>
<span class="s2">throw new </span><span class="s1">ActionFailureException(</span><span class="s4">&quot;cannot add local node&quot;</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">&quot;cannot find task's parent id locally&quot;</span><span class="s1">);</span>
<span class="s2">throw new </span><span class="s1">ActionFailureException(</span><span class="s4">&quot;cannot update local node&quot;</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">&quot;cannot find task's parent tasklist&quot;</span><span class="s1">);</span>
<span class="s2">throw new </span><span class="s1">ActionFailureException(</span><span class="s4">&quot;cannot add remote task&quot;</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&lt;Map.Entry&lt;String, TaskList&gt;&gt; iter = mGTaskListHashMap.entrySet().iterator();</span>
<span class="s2">while </span><span class="s1">(iter.hasNext()) {</span>
<span class="s1">Map.Entry&lt;String, TaskList&gt; 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">&quot;cannot find task's parent tasklist&quot;</span><span class="s1">);</span>
<span class="s2">throw new </span><span class="s1">ActionFailureException(</span><span class="s4">&quot;cannot update remote task&quot;</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">&amp;&amp; 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">&quot;(type&lt;&gt;? AND parent_id&lt;&gt;?)&quot;</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">&quot; DESC&quot;</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">&quot;something is missed&quot;</span><span class="s1">);</span>
<span class="s2">throw new </span><span class="s1">ActionFailureException(</span>
<span class="s4">&quot;some local items don't have gid after sync&quot;</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">&quot;failed to query local note to refresh sync id&quot;</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>