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.
rjgc/gtask/data/TaskList.java

442 lines
14 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;
/**
* 任务列表类表示Google Task中的任务列表
* 继承自Node管理一组Task子任务
*/
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;
}
/**
* 获取创建任务列表的JSON操作对象
* @param actionId 操作ID
* @return 包含创建参数的JSON对象
*/
public JSONObject getCreateAction(int actionId) {
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());
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;
}
/**
* 获取更新任务列表的JSON操作对象
* @param actionId 操作ID
* @return 包含更新参数的JSON对象
*/
public JSONObject getUpdateAction(int actionId) {
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 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;
}
/**
* 从远程JSON数据解析任务列表内容
* @param js 远程服务器返回的JSON对象
*/
public void setContentByRemoteJSON(JSONObject js) {
if (js != null) {
try {
// 解析ID
if (js.has(GTaskStringUtils.GTASK_JSON_ID)) {
setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID));
}
// 解析最后修改时间
if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) {
setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED));
}
// 解析名称
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");
}
}
}
/**
* 从本地JSON数据设置任务列表内容
* 将本地文件夹名称加上MIUI前缀作为远程任务列表名称
* @param js 本地文件夹JSON对象
*/
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) {
// 系统文件夹根据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();
}
}
/**
* 从任务列表内容生成本地文件夹JSON
* 移除MIUI前缀还原为本地文件夹名称
* @return 本地文件夹JSON对象
*/
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;
}
}
/**
* 根据本地数据库状态确定文件夹的同步操作类型
* 文件夹冲突时优先应用本地修改
* @param c 本地数据库游标
* @return 同步操作类型常量
*/
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())) {
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;
}
/**
* 获取子任务数量
* @return 子任务个数
*/
public int getChildTaskCount() {
return mChildren.size();
}
/**
* 添加子任务到列表末尾
* 自动设置前驱兄弟和父节点
* @param task 要添加的任务
* @return 添加成功返回true
*/
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;
}
/**
* 在指定位置插入子任务
* @param task 要添加的任务
* @param index 插入位置
* @return 添加成功返回true
*/
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;
}
/**
* 移除子任务
* @param 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) {
// 重置前驱兄弟和父节点
task.setPriorSibling(null);
task.setParent(null);
// 更新列表中后续任务的兄弟关系
if (index != mChildren.size()) {
mChildren.get(index).setPriorSibling(
index == 0 ? null : mChildren.get(index - 1));
}
}
}
return ret;
}
/**
* 移动子任务到指定位置
* @param task 要移动的任务
* @param index 目标位置
* @return 移动成功返回true
*/
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查找子任务
* @param gid 全局唯一标识符
* @return 找到的任务未找到返回null
*/
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;
}
/**
* 获取任务在列表中的索引
* @param task 目标任务
* @return 索引位置
*/
public int getChildTaskIndex(Task task) {
return mChildren.indexOf(task);
}
/**
* 通过索引获取子任务
* @param index 索引位置
* @return 子任务对象
*/
public Task getChildTaskByIndex(int index) {
if (index < 0 || index >= mChildren.size()) {
Log.e(TAG, "getTaskByIndex: invalid index");
return null;
}
return mChildren.get(index);
}
/**
* 通过Gid获取子任务
* @param gid 全局唯一标识符
* @return 子任务对象
*/
public Task getChilTaskByGid(String gid) {
for (Task task : mChildren) {
if (task.getGid().equals(gid))
return task;
}
return null;
}
/**
* 获取所有子任务列表
* @return 子任务ArrayList
*/
public ArrayList<Task> getChildTaskList() {
return this.mChildren;
}
/**
* 设置列表索引
* @param index 索引值
*/
public void setIndex(int index) {
this.mIndex = index;
}
/**
* 获取列表索引
* @return 索引值
*/
public int getIndex() {
return this.mIndex;
}
}