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.
test1/TaskList.java

464 lines
21 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* 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<Task> mChildren;
public TaskList() {
super();
mChildren = new ArrayList<Task>();
mIndex = 1;
}
/**
* 根据提供的操作ID生成创建任务的JSON对象
*
* @param actionId 操作ID用于标识此创建动作
* @return 包含创建任务所需信息的JSON对象
* @throws ActionFailureException 如果无法生成JSON对象则抛出此异常
*/
public JSONObject getCreateAction(int actionId) {
// 创建一个新的JSONObject来存储创建任务的动作信息
JSONObject js = new JSONObject();
try {
// 向JSONObject中添加动作类型这里指定为创建动作
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE);
// 向JSONObject中添加动作ID用于唯一标识此创建动作
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
// 向JSONObject中添加索引值可能用于在任务列表中的排序或定位
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex);
// 创建一个新的JSONObject来存储实体如任务组的增量信息
JSONObject entity = new JSONObject();
// 向实体JSONObject中添加任务组的名称
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
// 向实体JSONObject中添加创建者ID这里暂时设置为"null"(可能需要根据实际情况修改)
entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null");
// 向实体JSONObject中添加实体类型这里指定为任务组
entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE,
GTaskStringUtils.GTASK_JSON_TYPE_GROUP);
// 将包含实体增量信息的JSONObject添加到主JSONObject中
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
} catch (JSONException e) {
// 如果在创建或填充JSONObject时发生JSON异常则记录错误日志
Log.e(TAG, e.toString());
// 打印堆栈跟踪信息以帮助调试
e.printStackTrace();
// 抛出一个自定义异常表示无法生成任务创建的JSON对象
throw new ActionFailureException("fail to generate tasklist-create jsonobject");
}
// 返回包含创建任务所需信息的JSON对象
return js;
}
/**
* 根据提供的操作ID生成更新任务的JSON对象
*
* @param actionId 操作ID用于标识此更新动作
* @return 包含更新任务所需信息的JSON对象
* @throws ActionFailureException 如果无法生成JSON对象则抛出此异常
*/
public JSONObject getUpdateAction(int actionId) {
// 创建一个新的JSONObject来存储更新任务的动作信息
JSONObject js = new JSONObject();
try {
// 向JSONObject中添加动作类型这里指定为更新动作
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE);
// 向JSONObject中添加动作ID用于唯一标识此更新动作
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
// 向JSONObject中添加要更新的任务或实体的ID
js.put(GTaskStringUtils.GTASK_JSON_ID, getGid()); // 假设getGid()方法返回要更新的任务或实体的全局唯一标识符
// 创建一个新的JSONObject来存储实体如任务或任务组的增量信息
JSONObject entity = new JSONObject();
// 向实体JSONObject中添加任务或任务组的名称
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); // 假设getName()方法返回任务或任务组的名称
// 向实体JSONObject中添加一个标志表示任务或任务组是否被删除
// 注意:这里的逻辑可能需要根据实际情况调整,因为通常更新动作不会直接包含删除标志
// 除非这里的“删除”是指将任务标记为已删除状态,而不是从数据库中删除
entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted()); // 假设getDeleted()方法返回一个布尔值,表示任务或任务组是否被删除
// 将包含实体增量信息的JSONObject添加到主JSONObject中
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
} catch (JSONException e) {
// 如果在创建或填充JSONObject时发生JSON异常则记录错误日志
Log.e(TAG, e.toString());
// 打印堆栈跟踪信息以帮助调试
e.printStackTrace();
// 抛出一个自定义异常表示无法生成任务更新的JSON对象
throw new ActionFailureException("fail to generate tasklist-update jsonobject");
}
// 返回包含更新任务所需信息的JSON对象
return js;
}
/**
* 根据提供的JSON对象设置任务列表的内容
*
* @param js 包含任务列表内容的JSON对象
* @throws ActionFailureException 如果无法从JSON对象中获取任务列表内容则抛出此异常
*/
public void setContentByRemoteJSON(JSONObject js) {
// 首先检查传入的JSON对象是否为null
if (js != null) {
try {
// 尝试从JSON对象中获取任务或实体的ID
if (js.has(GTaskStringUtils.GTASK_JSON_ID)) {
// 如果存在ID字段则调用setGid方法设置任务或实体的ID
// 假设setGid方法接受一个字符串参数用于设置全局唯一标识符
setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID));
}
// 尝试从JSON对象中获取最后修改时间
if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) {
// 如果存在最后修改时间字段则调用setLastModified方法设置最后修改时间
// 假设setLastModified方法接受一个long类型的参数表示最后的修改时间戳
setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED));
}
// 尝试从JSON对象中获取任务或实体的名称
if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) {
// 如果存在名称字段则调用setName方法设置任务或实体的名称
// 假设setName方法接受一个字符串参数用于设置名称
setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME));
}
// 注意:这里可能还有其他字段需要处理,根据实际需求添加即可
} catch (JSONException e) {
// 如果在解析JSON对象时发生JSON异常则记录错误日志
Log.e(TAG, e.toString());
// 打印堆栈跟踪信息以帮助调试
e.printStackTrace();
// 抛出一个自定义异常表示无法从JSON对象中获取任务列表内容
throw new ActionFailureException("fail to get tasklist content from jsonobject");
}
}
// 如果传入的JSON对象为null则不进行任何操作或者可以根据实际需求添加null处理逻辑
}
/**
* 根据本地JSON对象设置内容该JSON对象代表一个笔记或文件夹
*
* @param js 包含笔记或文件夹信息的JSON对象
*/
public void setContentByLocalJSON(JSONObject js) {
// 首先检查传入的JSON对象是否为null或者是否不包含元数据头部假设代表笔记或文件夹的元数据
if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)) {
// 如果条件满足,记录一条警告日志,表示没有可用的内容来设置
Log.w(TAG, "setContentByLocalJSON: nothing is available");
// 注意这里没有返回或抛出异常方法将继续执行尽管后续操作可能因为js为null而失败
// 根据实际需求这里可能需要添加return语句来退出方法
}
try {
// 从JSON对象中获取代表笔记或文件夹的元数据JSON对象
JSONObject folder = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
// 根据元数据中的类型字段来判断是文件夹还是其他类型的笔记
int type = folder.getInt(NoteColumns.TYPE);
if (type == Notes.TYPE_FOLDER) {
// 如果是文件夹类型
String name = folder.getString(NoteColumns.SNIPPET); // 假设SNIPPET字段存储了文件夹的名称
// 设置名称前缀可能是为了区分或标记这是从MIUI系统导入的文件夹
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + name);
} else if (type == Notes.TYPE_SYSTEM) {
// 如果是系统类型的笔记
long id = folder.getLong(NoteColumns.ID); // 获取笔记或文件夹的ID
if (id == Notes.ID_ROOT_FOLDER) {
// 如果是根文件夹
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT);
} else if (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) {
// 如果在解析JSON对象时发生JSON异常则记录错误日志
Log.e(TAG, e.toString());
// 打印堆栈跟踪信息以帮助调试
e.printStackTrace();
// 注意:这里没有抛出异常或进行其他错误处理,根据实际需求可能需要添加
}
// 方法执行完毕,没有返回值
}
/**
* 从当前内容生成并返回一个代表文件夹或笔记的本地JSON对象
*
* @return 代表文件夹或笔记的JSON对象或者在发生错误时返回null
*/
public JSONObject getLocalJSONFromContent() {
try {
// 创建一个新的JSON对象它将作为返回的顶层对象
JSONObject js = new JSONObject();
// 创建一个新的JSON对象用于存储文件夹或笔记的元数据
JSONObject folder = new JSONObject();
// 获取当前对象的名称(可能是文件夹名)
String folderName = getName();
// 如果名称以特定的前缀开头假设这是为了标识从MIUI系统导入的文件夹则去除这个前缀
if (folderName.startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX)) {
folderName = folderName.substring(GTaskStringUtils.MIUI_FOLDER_PREFFIX.length());
}
// 将处理后的文件夹名存储在元数据JSON对象中
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); // 普通文件夹
}
// 将包含文件夹或笔记元数据的JSON对象添加到顶层JSON对象中
js.put(GTaskStringUtils.META_HEAD_NOTE, folder);
// 返回构建好的JSON对象
return js;
} catch (JSONException e) {
// 如果在创建或操作JSON对象时发生异常则记录错误日志
Log.e(TAG, e.toString());
// 打印堆栈跟踪信息以帮助调试
e.printStackTrace();
// 在发生异常时返回null
return null;
}
}
// 定义一个方法根据Cursor中的数据确定同步操作
public int getSyncAction(Cursor c) {
try {
// 检查本地是否有修改通过SqlNote.LOCAL_MODIFIED_COLUMN字段
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())) {
Log.e(TAG, "gtask id doesn't match"); // 日志记录错误
return SYNC_ACTION_ERROR; // 同步操作错误
}
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) {
boolean ret = false;
if (task != null && !mChildren.contains(task)) { // 检查任务不为空且不在列表中
ret = mChildren.add(task); // 添加任务到列表
if (ret) {
// 设置新添加任务的先前兄弟任务和父任务
task.setPriorSibling(mChildren.isEmpty() ? null : mChildren.get(mChildren.size() - 1));
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); // 检查任务是否已存在
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; // 始终返回true因为添加操作在前面的条件中已确认
}
// 从列表中移除一个子任务
public boolean removeChildTask(Task task) {
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()) {
mChildren.get(index).setPriorSibling(index == 0 ? null : mChildren.get(index - 1));
}
}
}
return ret; // 返回移除是否成功
}
// 方法用于移动子任务在列表中的位置
public boolean moveChildTask(Task task, int index) {
// 检查提供的索引是否有效
if (index < 0 || index >= mChildren.size()) {
Log.e(TAG, "move child task: invalid index"); // 索引无效时记录错误日志
return false; // 返回失败
}
// 查找任务在子任务列表中的当前位置
int pos = mChildren.indexOf(task);
// 如果任务不在列表中
if (pos == -1) {
Log.e(TAG, "move child task: the task should in the list"); // 记录错误日志
return false; // 返回失败
}
// 如果任务已经在目标索引位置,则无需移动
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); // 获取当前任务
if (t.getGid().equals(gid)) { // 如果任务的GID匹配
return t; // 返回该任务
}
}
return null; // 如果没有找到匹配的任务返回null
}
// 根据任务对象获取其在子任务列表中的索引
public int getChildTaskIndex(Task task) {
return mChildren.indexOf(task); // 返回任务在列表中的索引,如果不在列表中则返回-1
}
// 根据索引获取子任务
public Task getChildTaskByIndex(int index) {
// 检查索引是否有效
if (index < 0 || index >= mChildren.size()) {
Log.e(TAG, "getTaskByIndex: invalid index"); // 记录错误日志
return null; // 返回null
}
return mChildren.get(index); // 返回指定索引处的任务
}
// 另一个根据GID查找子任务的方法与findChildTaskByGid功能相同但使用了增强的for循环
public Task getChilTaskByGid(String gid) {
for (Task task : mChildren) {
if (task.getGid().equals(gid)) // 如果任务的GID匹配
return task; // 返回该任务
}
return null; // 如果没有找到匹配的任务返回null
}
public ArrayList<Task> getChildTaskList() {
return this.mChildren;
}
public void setIndex(int index) {
this.mIndex = index;
}
public int getIndex() {
return this.mIndex;
}
}