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.
123456/java/net/micode/notes/gtask/data/TaskList.java

404 lines
18 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.
* 总体分析
这段 Java 代码定义了TaskList类它继承自Node类主要用于处理任务列表相关的数据与操作涵盖了任务列表在与 GTask 交互时创建、更新操作对应的 JSON 数据构建及解析同步操作类型判断以及对其包含的子任务Task对象的增删改查、位置移动、根据标识查找等一系列管理操作同时还有自身索引属性的设置与获取功能在构建具有层级结构的任务管理体系以及实现任务列表数据的同步、展示与操作等业务场景中起着关键作用。
函数分析
TaskList类构造函数
所属类TaskList
功能调用父类构造函数进行初始化后创建一个空的ArrayList用于存储子任务Task对象并将自身索引属性mIndex初始化为1为后续管理子任务及记录列表相关属性做准备。
getCreateAction方法
所属类TaskList
功能创建一个新的JSONObject对象按照 GTask 相关格式要求向其中添加动作类型创建、动作ID、索引、任务列表实体相关数据名称、创建者ID、类型等等信息若添加过程出现JSONException则记录错误日志、打印堆栈信息并抛出异常最终返回构建好的用于创建任务列表的JSONObject用于生成创建任务列表操作对应的 JSON 数据结构。
getUpdateAction方法
所属类TaskList
功能同样先创建一个JSONObject对象然后依据 GTask 规范向其中添加动作类型更新、动作ID、任务列表ID以及任务列表实体更新相关的数据名称、删除状态等若出现JSONException则记录错误日志、打印堆栈信息并抛出异常最后返回该JSONObject用于构建任务列表更新操作对应的 JSON 数据内容。
setContentByRemoteJSON方法
所属类TaskList
功能在传入的JSONObject不为null的前提下尝试从其中获取并设置任务列表的相关属性信息包括ID、最后修改时间、名称等若获取过程出现JSONException则记录错误日志、打印堆栈信息并抛出异常用于根据远程传来的 JSON 数据更新任务列表对象的属性内容。
setContentByLocalJSON方法
所属类TaskList
功能先对传入的JSONObject进行有效性判断若不符合要求则记录警告日志若符合则尝试从中解析出笔记相关信息根据笔记类型文件夹类型、系统类型等进行不同处理设置任务列表的名称用于依据本地 JSON 数据设置任务列表的名称等相关属性。
getLocalJSONFromContent方法
所属类TaskList
功能创建一个新的JSONObject对象按照特定格式从任务列表名称等信息中提取并构建包含笔记相关信息的JSONObject添加到外层JSONObject中并返回若过程中出现JSONException则记录错误日志、打印堆栈信息并返回null用于生成基于任务列表当前内容的本地 JSON 数据表示形式。
getSyncAction方法
所属类TaskList
功能通过判断本地是否有更新依据LOCAL_MODIFIED_COLUMN的值以及同步ID与最后修改时间是否匹配、GTask ID是否一致等条件按照不同情况返回对应的同步操作类型常量如无操作、本地更新、远程更新、出现错误等若过程中出现异常则记录错误日志并打印堆栈信息用于判断任务列表在数据同步过程中的操作类型。
getChildTaskCount方法
所属类TaskList
功能返回存储子任务的ArrayList的大小也就是任务列表中包含的子任务数量用于获取任务列表中子任务的个数信息便于展示、统计等业务操作。
addChildTask(Task task)方法
所属类TaskList
功能判断传入的Task对象不为null且尚未包含在子任务列表中时将其添加到子任务列表中添加成功后设置该任务的前置任务若列表为空则为null否则为列表中最后一个任务和父任务当前任务列表最后返回添加操作是否成功的布尔值用于向任务列表中添加单个子任务并建立任务之间的关联关系。
addChildTask(Task task, int index)方法
所属类TaskList
功能先对传入的索引参数进行合法性判断若索引无效则记录错误日志并返回false。接着判断任务不为null且不在子任务列表中时将其添加到指定索引位置然后更新任务列表中相关任务的前置任务关系设置新添加任务的前置任务以及其后续任务的前置任务最后返回添加操作是否成功的布尔值用于在指定位置向任务列表中添加子任务并正确维护任务间的顺序关系。
removeChildTask(Task task)方法
所属类TaskList
功能先查找传入任务在子任务列表中的索引若索引存在则从列表中移除该任务移除成功后重置该任务的前置任务和父任务为null同时更新任务列表中后续任务若有的前置任务关系最后返回移除操作是否成功的布尔值用于从任务列表中移除指定的子任务并调整相关任务关系。
moveChildTask(Task task, int index)方法
所属类TaskList
功能先对目标索引进行合法性判断若索引无效则记录错误日志并返回false接着判断任务是否在任务列表中若不在则同样记录错误日志并返回false若任务所在位置与目标索引相同则直接返回true否则先移除该任务再将其添加到目标索引位置通过调用前面的相关方法实现任务在列表中的位置移动最后返回移动操作是否成功的布尔值用于在任务列表中移动指定子任务到新的位置。
findChildTaskByGid(String gid)方法
所属类TaskList
功能遍历子任务列表查找Gid属性与传入gid字符串相等的子任务若找到则返回该任务若遍历完未找到则返回null用于根据任务的唯一标识Gid在任务列表中查找对应的子任务。
getChildTaskIndex(Task task)方法
所属类TaskList
功能:返回传入任务在子任务列表中的索引位置,若任务不在列表中则返回-1用于获取子任务在任务列表中的位置信息便于排序、查找等操作。
getChildTaskByIndex(int index)方法
所属类TaskList
功能先对传入的索引参数进行合法性判断若索引无效则记录错误日志并返回null若合法则从子任务列表中获取并返回对应索引位置的子任务对象用于根据索引获取任务列表中的指定子任务。
getChilTaskByGid(String gid)方法
所属类TaskList
功能遍历子任务列表查找Gid属性与传入gid字符串匹配的子任务找到则返回该任务若遍历完未找到则返回null与findChildTaskByGid方法功能类似同样用于根据任务标识查找对应的子任务。
getChildTaskList方法
所属类TaskList
功能返回存储子任务的ArrayList对象也就是获取任务列表包含的所有子任务列表便于对所有子任务进行批量操作或获取相关信息等操作。
setIndex(int index)方法
所属类TaskList
功能接收一个整数参数index将其赋值给mIndex属性用于更新任务列表的索引属性值满足业务场景中对任务列表索引修改的需求。
getIndex方法
所属类TaskList
功能返回mIndex属性的值也就是获取任务列表当前的索引值用于获取任务列表的索引相关信息在展示、排序等场景下可能会用到。
*/
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;
}
public JSONObject getCreateAction(int actionId) {
JSONObject js = new JSONObject();
try {
// action_type
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE);
// action_id
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
// index
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex);
// entity_delta
JSONObject entity = new JSONObject();
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null");
entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE,
GTaskStringUtils.GTASK_JSON_TYPE_GROUP);
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");
}
return js;
}
public JSONObject getUpdateAction(int actionId) {
JSONObject js = new JSONObject();
try {
// action_type
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE);
// action_id
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
// id
js.put(GTaskStringUtils.GTASK_JSON_ID, getGid());
// entity_delta
JSONObject entity = new JSONObject();
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted());
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");
}
return js;
}
public void setContentByRemoteJSON(JSONObject js) {
if (js != null) {
try {
// id
if (js.has(GTaskStringUtils.GTASK_JSON_ID)) {
setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID));
}
// last_modified
if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) {
setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED));
}
// 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) {
if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)) {
Log.w(TAG, "setContentByLocalJSON: nothing is avaiable");
}
try {
JSONObject folder = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
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) {
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 js = new 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.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);
js.put(GTaskStringUtils.META_HEAD_NOTE, folder);
return js;
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
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) {
boolean ret = false;
if (task != null && !mChildren.contains(task)) {
ret = mChildren.add(task);
if (ret) {
// need to set prior sibling and parent
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);
// update the task list
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) {
boolean ret = false;
int index = mChildren.indexOf(task);
if (index != -1) {
ret = mChildren.remove(task);
if (ret) {
// reset prior sibling and parent
task.setPriorSibling(null);
task.setParent(null);
// update the task list
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));
}
public Task findChildTaskByGid(String gid) {
for (int i = 0; i < mChildren.size(); i++) {
Task t = mChildren.get(i);
if (t.getGid().equals(gid)) {
return t;
}
}
return null;
}
public int getChildTaskIndex(Task task) {
return mChildren.indexOf(task);
}
public Task getChildTaskByIndex(int index) {
if (index < 0 || index >= mChildren.size()) {
Log.e(TAG, "getTaskByIndex: invalid index");
return null;
}
return mChildren.get(index);
}
public Task getChilTaskByGid(String gid) {
for (Task task : mChildren) {
if (task.getGid().equals(gid))
return task;
}
return null;
}
public ArrayList<Task> getChildTaskList() {
return this.mChildren;
}
public void setIndex(int index) {
this.mIndex = index;
}
public int getIndex() {
return this.mIndex;
}
}