/* * 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 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; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; public class TaskList extends Node { // 类标签,用于日志输出 private static final String TAG = TaskList.class.getSimpleName(); // 任务列表的索引 private int mIndex; // 子任务列表 private ArrayList mChildren; // 构造方法 public TaskList() { super(); // 初始化子任务列表 mChildren = new ArrayList(); // 设置默认索引值为1 mIndex = 1; } // 获取创建操作的JSON对象 public JSONObject getCreateAction(int actionId) { // 创建JSON对象 JSONObject js = new JSONObject(); try { // 添加操作类型 js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE); // 添加操作ID js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); // 添加索引 js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex); // 添加实体变更信息 JSONObject entity = new JSONObject(); // 添加名称 entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); // 添加创建者ID,此处为"null" entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null"); // 添加实体类型 entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE, GTaskStringUtils.GTASK_JSON_TYPE_GROUP); // 将实体变更信息添加到主JSON对象 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"); } // 返回创建操作的JSON对象 return js; } } public JSONObject getUpdateAction(int actionId) { // 创建一个空的JSONObject对象 JSONObject js = new JSONObject(); try { // 添加操作类型,表示这是一个更新操作 js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE); // 添加操作ID js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); // 添加任务列表的ID 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 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-update jsonobject"); } // 返回包含更新操作的JSONObject return js; } public void setContentByRemoteJSON(JSONObject js) { // 检查传入的JSONObject是否为null if (js != null) { try { // 检查JSONObject中是否包含id字段,并设置gid if (js.has(GTaskStringUtils.GTASK_JSON_ID)) { setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID)); } // 检查JSONObject中是否包含last_modified字段,并设置最后修改时间 if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) { setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)); } // 检查JSONObject中是否包含name字段,并设置名称 if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) { setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME)); } } catch (JSONException e) { // 记录错误日志 Log.e(TAG, e.toString()); // 打印异常堆栈信息 e.printStackTrace(); // 抛出操作失败异常 throw new ActionFailureException("fail to get tasklist content from jsonobject"); } } } public void setContentByLocalJSON(JSONObject js) { // 检查传入的JSONObject是否为null或者不包含META_HEAD_NOTE字段 if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)) { // 记录警告日志 Log.w(TAG, "setContentByLocalJSON: nothing is available"); } try { // 从JSONObject中获取META_HEAD_NOTE对象 JSONObject folder = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); // 检查folder的类型是否为文件夹 if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) { // 获取文件夹名称,并设置当前对象的名称 String name = folder.getString(NoteColumns.SNIPPET); setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + name); } else if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) { // 检查系统文件夹类型,并根据ID设置名称 if (folder.getLong(NoteColumns.ID) == Notes.ID_ROOT_FOLDER) setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT); else if (folder.getLong(NoteColumns.ID) == Notes.ID_CALL_RECORD_FOLDER) 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) { // 记录错误日志 Log.e(TAG, e.toString()); // 打印异常堆栈信息 e.printStackTrace(); } } public JSONObject getLocalJSONFromContent() { try { // 创建一个新的JSONObject JSONObject js = new JSONObject(); // 创建一个用于存储文件夹信息的JSONObject JSONObject folder = new JSONObject(); // 获取当前对象的名称 String folderName = getName(); // 如果名称以特定前缀开始,则去除前缀 if (getName().startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX)) folderName = folderName.substring(GTaskStringUtils.MIUI_FOLDER_PREFFIX.length(), folderName.length()); // 将处理后的文件夹名称放入folder对象 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对象放入js对象中 js.put(GTaskStringUtils.META_HEAD_NOTE, folder); // 返回构建好的JSONObject return js; } catch (JSONException e) { // 记录错误日志 Log.e(TAG, e.toString()); // 打印异常堆栈信息 e.printStackTrace(); // 发生异常时返回null return null; } } public int getSyncAction(Cursor c) { try { // 检查是否有本地修改 if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) { // 没有本地更新 if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { // 双方都没有更新 return SYNC_ACTION_NONE; } else { // 应用远程数据到本地 return SYNC_ACTION_UPDATE_LOCAL; } } else { // 验证gtask id是否匹配 if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) { // gtask id不匹配,记录错误日志 Log.e(TAG, "gtask id doesn't match"); return SYNC_ACTION_ERROR; } // 检查同步ID是否与最后修改时间一致 if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { // 只有本地修改 return SYNC_ACTION_UPDATE_REMOTE; } else { // 对于文件夹冲突,仅应用本地修改 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; // 检查任务对象是否为null并且子任务列表中不包含该任务 if (task != null && !mChildren.contains(task)) { // 将任务添加到子任务列表中,并更新返回值 ret = mChildren.add(task); // 如果添加成功 if (ret) { // 需要设置前一个兄弟节点和父节点 // 如果子任务列表为空,则前一个兄弟节点为null,否则为列表中的最后一个元素 task.setPriorSibling(mChildren.isEmpty() ? null : mChildren.get(mChildren.size() - 1)); // 设置当前TaskList为任务的父节点 task.setParent(this); } } // 返回是否成功添加任务 return ret; } public boolean addChildTask(Task task, int index) { // 检查索引是否有效 if (index < 0 || index > mChildren.size()) { // 记录错误日志 Log.e(TAG, "add child task: invalid index"); // 返回添加失败 return false; } // 查找任务是否已存在于子任务列表中 int pos = mChildren.indexOf(task); // 如果任务不为null且不在子任务列表中 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); // 设置当前任务的前一个兄弟节点 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 = mChildren.remove(task); // 如果移除成功 if (ret) { // 重置任务的前一个兄弟节点和父节点 task.setPriorSibling(null); task.setParent(null); // 更新任务列表 // 如果移除的任务不是列表中的最后一个 if (index != mChildren.size()) { // 设置新的前一个兄弟节点 // 如果移除的是第一个任务,则新的前一个兄弟节点为null // 否则为列表中前一个任务 mChildren.get(index).setPriorSibling( index == 0 ? null : mChildren.get(index - 1)); } } } // 返回是否成功移除任务 return ret; } // 移动子任务到指定索引位置的方法 public boolean moveChildTask(Task task, int index) { // 检查索引是否有效,无效则打印错误日志并返回false if (index < 0 || index >= mChildren.size()) { 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; // 移除任务后尝试在指定位置添加任务,成功则返回true,失败则返回false return (removeChildTask(task) && addChildTask(task, index)); } // 通过GID查找子任务的方法 public Task findChildTaskByGid(String gid) { // 遍历子任务列表,查找GID匹配的任务 for (int i = 0; i < mChildren.size(); i++) { Task t = mChildren.get(i); if (t.getGid().equals(gid)) { return t; } }// 如果没有找到,则返回null return null; } // 获取子任务索引的方法 public int getChildTaskIndex(Task task) { // 返回任务在列表中的索引位置 return mChildren.indexOf(task); } // 通过索引获取子任务的方法 public Task getChildTaskByIndex(int index) { // 检查索引是否有效,无效则打印错误日志并返回null if (index < 0 || index >= mChildren.size()) { Log.e(TAG, "getTaskByIndex: invalid index"); return null; } // 返回指定索引位置的子任务 return mChildren.get(index); } // 通过GID获取子任务的方法(存在拼写错误,应为getChildTaskByGid) public Task getChilTaskByGid(String gid) { // 遍历子任务列表,查找GID匹配的任务 for (Task task : mChildren) { 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;// 返回当前对象的索引值 } }