/* * 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. */ package net.micode.notes.gtask.data; import java.util.ArrayList; import org.json.JSONException; import org.json.JSONObject; import android.database.Cursor; import android.util.Log; import net.micode.notes.data.Notes; import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.gtask.exception.ActionFailureException; import net.micode.notes.tool.GTaskStringUtils; public class TaskList extends Node { private static final String TAG = TaskList.class.getSimpleName();// tag标记 private int mIndex;// 当前TaskList的指针 private ArrayList mChildren;// 类中主要的保存数据的单元,用来实现一个以Task为元素的ArrayList public TaskList() { super(); mChildren = new ArrayList(); mIndex = 1; } // 根据传入的 actionId 生成一个包含一定数据的 JSONObject 实体 public JSONObject getCreateAction(int actionId) { // 创建一个新的JSONObject对象,用于存储要返回的JSON数据 JSONObject js = new JSONObject(); try { // 将动作类型设为创建类型,并添加到JSONObject中 js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE); // 将传入的actionId参数设置为action_id,表示该操作的唯一标识,并添加到JSONObject中 js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); // 将TaskList对象的mIndex属性设置为index,表示当前TaskList的指针位置,并添加到JSONObject中 js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex); // 创建一个新的JSONObject对象entity,用于存储实体信息 JSONObject entity = new JSONObject(); // 将任务列表的名称信息添加到entity中 entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); // 将创建者ID设置为"null",并添加到entity中 entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null"); // 将实体类型设为群组类型,并添加到entity中 entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE, GTaskStringUtils.GTASK_JSON_TYPE_GROUP); // 将存储实体信息的entity对象添加到JSONObject中 js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); } catch (JSONException e) { // 如果出现异常,则打印错误信息并抛出自定义异常 Log.e(TAG, e.toString()); e.printStackTrace(); throw new ActionFailureException("fail to generate tasklist-create jsonobject"); } // 返回构建好的JSONObject对象 return js; } public JSONObject getUpdateAction(int actionId) { // 创建一个新的JSONObject对象 JSONObject js = new JSONObject(); try { // 设置action_type字段为UPDATE js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE); // 设置action_id字段为传入的actionId参数值 js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); // 设置id字段为当前任务的gid(全局唯一标识符) js.put(GTaskStringUtils.GTASK_JSON_ID, getGid()); // 创建一个新的JSONObject对象,用于存储任务的实体信息 JSONObject entity = new JSONObject(); // 设置实体的名称字段为当前任务的名称 entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); // 设置实体的删除状态字段为当前任务的删除状态 entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted()); // 将实体信息添加到主JSONObject对象中的entity_delta字段 js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); } catch (JSONException e) { // 捕获JSONException异常并记录异常信息 Log.e(TAG, e.toString()); e.printStackTrace(); // 抛出自定义的ActionFailureException异常,提示生成任务更新JSONObject对象失败 throw new ActionFailureException("fail to generate tasklist-update jsonobject"); } // 返回构建好的JSONObject对象 return js; } public void setContentByRemoteJSON(JSONObject js) { // 检查传入的JSONObject对象是否为空 if (js != null) { try { // 解析并设置任务的id字段,如果JSONObject包含该字段 if (js.has(GTaskStringUtils.GTASK_JSON_ID)) { setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID)); } // 解析并设置任务的last_modified字段,如果JSONObject包含该字段 if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) { setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)); } // 解析并设置任务的name字段,如果JSONObject包含该字段 if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) { setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME)); } } catch (JSONException e) { // 捕获JSONException异常并记录异常信息 Log.e(TAG, e.toString()); e.printStackTrace(); // 抛出自定义的ActionFailureException异常,提示从JSONObject获取任务内容失败 throw new ActionFailureException("fail to get tasklist content from jsonobject"); } } } public void setContentByLocalJSON(JSONObject js) { // 检查传入的JSONObject对象是否为空,或者是否包含了指定的元数据 if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)) { // 如果条件不满足,则记录警告日志 Log.w(TAG, "setContentByLocalJSON: nothing is avaiable"); } try { // 从JSONObject中获取名为META_HEAD_NOTE的子JSONObject JSONObject folder = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); // 判断获取的folder的类型 if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) { // 如果是文件夹类型,则获取文件夹的名称,并在前面添加MIUI_FOLDER_PREFFIX前缀,然后设置为任务的名称 String name = folder.getString(NoteColumns.SNIPPET); setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + name); } else if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) { // 如果是系统类型的文件夹 if (folder.getLong(NoteColumns.ID) == Notes.ID_ROOT_FOLDER) // 如果是根文件夹,则设置名称为MIUI_FOLDER_PREFFIX + FOLDER_DEFAULT setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT); else if (folder.getLong(NoteColumns.ID) == Notes.ID_CALL_RECORD_FOLDER) // 如果是通话记录文件夹,则设置名称为MIUI_FOLDER_PREFFIX + FOLDER_CALL_NOTE setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_CALL_NOTE); else // 如果是其他系统文件夹,则记录错误日志 Log.e(TAG, "invalid system folder"); } else { // 如果是其他类型的文件夹,则记录错误日志 Log.e(TAG, "error type"); } } catch (JSONException e) { // 捕获JSONException异常并记录异常信息 Log.e(TAG, e.toString()); e.printStackTrace(); } } public JSONObject getLocalJSONFromContent() { try { // 创建一个新的JSONObject对象 JSONObject js = new JSONObject(); // 创建一个用于存储文件夹信息的JSONObject对象 JSONObject folder = new JSONObject(); // 获取任务的名��� String folderName = getName(); // 如果任务名称以MIUI_FOLDER_PREFFIX前缀开头,则去除前缀 if (getName().startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX)) folderName = folderName.substring(GTaskStringUtils.MIUI_FOLDER_PREFFIX.length(), folderName.length()); // 将文件夹名称添加到folder JSONObject中 folder.put(NoteColumns.SNIPPET, folderName); // 判断文件夹名称是否为系统默认文件夹名称或者通话记录文件夹名称,如果是则设置类型为系统文件夹,否则设置为普通文件夹 if (folderName.equals(GTaskStringUtils.FOLDER_DEFAULT) || folderName.equals(GTaskStringUtils.FOLDER_CALL_NOTE)) folder.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); else folder.put(NoteColumns.TYPE, Notes.TYPE_FOLDER); // 将存储文件夹信息的folder JSONObject添加到js JSONObject中 js.put(GTaskStringUtils.META_HEAD_NOTE, folder); // 返回构建好的JSONObject对象 return js; } catch (JSONException e) { // 捕获JSONException异常并记录异常信息 Log.e(TAG, e.toString()); e.printStackTrace(); // 返回null表示发生异常 return null; } } public int getSyncAction(Cursor c) { try { if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) { // there is no local update if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { // no update both side return SYNC_ACTION_NONE; } else { // apply remote to local return SYNC_ACTION_UPDATE_LOCAL; } } else { // validate gtask id if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) { Log.e(TAG, "gtask id doesn't match"); return SYNC_ACTION_ERROR; } if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { // local modification only return SYNC_ACTION_UPDATE_REMOTE; } else { // for folder conflicts, just apply local modification return SYNC_ACTION_UPDATE_REMOTE; } } } catch (Exception e) { Log.e(TAG, e.toString()); e.printStackTrace(); } return SYNC_ACTION_ERROR; } public int getChildTaskCount() { return mChildren.size(); } public boolean addChildTask(Task task) { // 初始化返回值为false boolean ret = false; // 检查传入的任务对象是否为空,并且该任务对象不在子任务列表中 if (task != null && !mChildren.contains(task)) { // 将任务对象添加到子任务列表中,并将添加结果保存到ret变量中 ret = mChildren.add(task); // 如果成功添加任务,则需要设置任务的前一个兄弟节点和父节点 if (ret) { // 设置任务的前一个兄弟节点,如果子任务列表为空,则前一个兄弟节点为null,否则为子任务列表中最后一个任务 task.setPriorSibling(mChildren.isEmpty() ? null : mChildren .get(mChildren.size() - 1)); // 设置任务的父节点为当前任务对象 task.setParent(this); } } // 返回添加任务的结果 return ret; } public boolean addChildTask(Task task, int index) { // 检查传入的索引是否合法,即不小于0且不大于子任务列表的大小 if (index < 0 || index > mChildren.size()) { // 如果索引非法,则记录错误日志并返回false Log.e(TAG, "add child task: invalid index"); return false; } // 查找任务在子任务列表中的位置 int pos = mChildren.indexOf(task); // 如果任务不为空且不在子任务列表中 if (task != null && pos == -1) { // 将任务添加到指定位置 mChildren.add(index, task); // 更新任务列表中的任务关系 Task preTask = null; Task afterTask = null; // 获取新添加任务的前一个任务和后一个任务 if (index != 0) preTask = mChildren.get(index - 1); if (index != mChildren.size() - 1) afterTask = mChildren.get(index + 1); // 设置新添加任务的前一个兄弟节点为preTask task.setPriorSibling(preTask); // 如果存在后一个任务,则将其前一个兄弟节点设置为新添加的任务 if (afterTask != null) afterTask.setPriorSibling(task); } // 返回添加任务的结果 return true; } public boolean removeChildTask(Task task) { // 初始化返回值为false boolean ret = false; // 获取任务在子任务列表中的索引 int index = mChildren.indexOf(task); // 如果任务存在于子任务列表中 if (index != -1) { // 从子任务列表中移除任务,并将移除结果保存到ret变量中 ret = mChildren.remove(task); // 如果成功移除任务 if (ret) { // 重置移除任务的前一个兄弟节点和父节点 task.setPriorSibling(null); task.setParent(null); // 更新任务列表中的任务关系 if (index != mChildren.size()) { // 如果移除的任务不是列表中的最后一个任务,则将后一个任务的前一个兄弟节点设置为移除任务的前一个任务 mChildren.get(index).setPriorSibling( index == 0 ? null : mChildren.get(index - 1)); } } } // 返回移除任务的结果 return ret; } public boolean moveChildTask(Task task, int index) { // 检查传入的索引是否合法,即不小于0且小于子任务列表的大小 if (index < 0 || index >= mChildren.size()) { // 如果索引非法,则记录错误日志并返回false Log.e(TAG, "move child task: invalid index"); return false; } // 查找任务在子任务列表中的位置 int pos = mChildren.indexOf(task); // 如果任务不在子任务列表中,则记录错误日志并返回false if (pos == -1) { Log.e(TAG, "move child task: the task should in the list"); return false; } // 如果任务已经在目标位置上,则直接返回true if (pos == index) return true; // 先移除任务,然后再添加到目标位置上 return (removeChildTask(task) && addChildTask(task, index)); } // 根据任务的gid查找子任务 public Task findChildTaskByGid(String gid) { // 遍历子任务列表 for (int i = 0; i < mChildren.size(); i++) { Task t = mChildren.get(i); // 如果找到gid匹配的任务,则返回该任务 if (t.getGid().equals(gid)) { return t; } } // 如果没有找到匹配的任务,则返回null return null; } // 获取子任务在子任务列表中的索引 public int getChildTaskIndex(Task task) { return mChildren.indexOf(task); } // 根据索引获取子任务 public Task getChildTaskByIndex(int index) { // 检查传入的索引是否合法 if (index < 0 || index >= mChildren.size()) { // 如果索引非法,则记录错误日志并返回null Log.e(TAG, "getTaskByIndex: invalid index"); return null; } // 返回索引处的子任务 return mChildren.get(index); } // 根据gid获取子任务 public Task getChilTaskByGid(String gid) { // 遍历子任务列表 for (Task task : mChildren) { // 如果找到gid匹配的任务,则返回该任务 if (task.getGid().equals(gid)) return task; } // 如果没有找到匹配的任务,则返回null return null; } // 获取子任务列表 public ArrayList getChildTaskList() { return this.mChildren; } // 设置任务在父任务列表中的索引 public void setIndex(int index) { this.mIndex = index; } // 获取任务在父任务列表中的索引 public int getIndex() { return this.mIndex; } }