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.
test123/Task.java

412 lines
17 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.text.TextUtils;
import android.util.Log;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.DataConstants;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.gtask.exception.ActionFailureException;
import net.micode.notes.tool.GTaskStringUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
// Task类继承自Node类表示一个任务节点
public class Task extends Node {
// 类的标记,用于日志输出
private static final String TAG = Task.class.getSimpleName();
// 表示任务是否完成
private boolean mCompleted;
// 任务备注
private String mNotes;
// 任务的元信息
private JSONObject mMetaInfo;
// 当前任务的前一个兄弟节点
private Task mPriorSibling;
// 当前任务的父任务列表
private TaskList mParent;
// 无参构造方法
public Task() {
super();
mCompleted = false;// 初始化时任务未完成
mNotes = null;// 备注
mPriorSibling = null;// 前一个兄弟节点
mParent = null;// 父任务列表
mMetaInfo = null; // 元信息
}
// 获取创建任务的JSON动作对象
public JSONObject getCreateAction(int actionId) {
JSONObject js = new JSONObject();;// 创建一个新的JSON对象
try {
// action_type // 设置动作类型为创建
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE);
// action_id // 设置动作ID
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
// index // 设置任务在父列表中的索引
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mParent.getChildTaskIndex(this));
// entity_delta // 设置实体变化信息
JSONObject entity = new JSONObject();
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());// 任务名称
entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null");// 创建者ID
entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE,
GTaskStringUtils.GTASK_JSON_TYPE_TASK);// 实体类型为任务
if (getNotes() != null) {// 如果获取到的备注信息不为空,则将备注信息添加到实体变化信息中
entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes());// 任务备注
}
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);// 将实体变化信息放入动作对象
// parent_id // 设置父任务ID
js.put(GTaskStringUtils.GTASK_JSON_PARENT_ID, mParent.getGid());// 获取父任务列表的GID并设置为父任务ID
// dest_parent_type// 设置目标父类型为任务组
js.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT_TYPE,
GTaskStringUtils.GTASK_JSON_TYPE_GROUP);// 指定目标父类型为任务组
// list_id// 设置列表ID这里同样使用父任务列表的GID
js.put(GTaskStringUtils.GTASK_JSON_LIST_ID, mParent.getGid());// 获取父任务列表的GID并设置为列表ID
// prior_sibling_id// 如果存在前一个兄弟节点则设置前一个兄弟节点的ID
if (mPriorSibling != null) {
js.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, mPriorSibling.getGid());// 获取前一个兄弟节点的GID并设置为前一个兄弟节点ID
}
// 如果在创建JSON对象过程中发生异常则捕获异常并记录日志
} catch (JSONException e) { // 如果发生JSON异常则输出日志
Log.e(TAG, e.toString());// 输出异常信息到日志
e.printStackTrace();// 打印异常堆栈信息
throw new ActionFailureException("fail to generate task-create jsonobject");// 抛出操作失败异常
}
return js;// 返回创建的JSON动作对象
}
// 获取更新任务的JSON动作对象
public JSONObject getUpdateAction(int actionId) {
JSONObject js = new JSONObject();// 创建一个新的JSON对象
try {
// action_type // 设置动作类型为更新
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE);
// action_id // 设置动作ID
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
// id // 设置任务的ID
js.put(GTaskStringUtils.GTASK_JSON_ID, getGid());// 获取当前任务的GID并设置为ID
// entity_delta // 设置实体变化信息
JSONObject entity = new JSONObject();
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());// 更新任务名称
if (getNotes() != null) {
entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes()); // 更新任务备注
}
entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted());// 更新任务是否被删除的状态
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); // 将实体变化信息放入动作对象
// 如果在创建JSON对象过程中发生异常则捕获异常并记录日志
} catch (JSONException e) {
Log.e(TAG, e.toString());// 输出异常信息到日志
e.printStackTrace();// 打印异常堆栈信息
throw new ActionFailureException("fail to generate task-update jsonobject");// 抛出操作失败异常
}
return js; // 返回创建的JSON动作对象
}
/**
* 根据远程JSON对象设置任务内容
* @param js 远程JSON对象
*/
public void setContentByRemoteJSON(JSONObject js) {
if (js != null) { // 如果JSON对象不为空
try {
// id // 设置任务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));
}
// notes // 设置任务备注
if (js.has(GTaskStringUtils.GTASK_JSON_NOTES)) {
setNotes(js.getString(GTaskStringUtils.GTASK_JSON_NOTES));
}
// deleted // 设置任务是否被删除
if (js.has(GTaskStringUtils.GTASK_JSON_DELETED)) {
setDeleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_DELETED));
}
// completed // 设置任务是否已完成
if (js.has(GTaskStringUtils.GTASK_JSON_COMPLETED)) {
setCompleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_COMPLETED));
}
} catch (JSONException e) {
Log.e(TAG, e.toString());// 记录异常信息到日志
e.printStackTrace(); // 打印异常堆栈信息
throw new ActionFailureException("fail to get task content from jsonobject");// 抛出操作失败异常
}
}
}
/**
* 根据本地JSON对象设置任务内容
* @param js 本地JSON对象
*/
public void setContentByLocalJSON(JSONObject js) {
if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)
|| !js.has(GTaskStringUtils.META_HEAD_DATA)) {
Log.w(TAG, "setContentByLocalJSON: nothing is avaiable");
}
try {
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);// 获取note部分的JSON对象
JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);// 获取data部分的JSONArray
if (note.getInt(NoteColumns.TYPE) != Notes.TYPE_NOTE) {// 如果note的类型不是笔记类型
Log.e(TAG, "invalid type"); // 记录错误信息到日志
return;// 结束方法执行
}
// 遍历dataArray数组
for (int i = 0; i < dataArray.length(); i++) {
JSONObject data = dataArray.getJSONObject(i); // 获取数组中的每个JSONObject
// 如果数据类型是笔记
if (TextUtils.equals(data.getString(DataColumns.MIME_TYPE), DataConstants.NOTE)) {// 设置任务名称
setName(data.getString(DataColumns.CONTENT));// 设置任务名称
break;// 找到匹配的数据后跳出循环
}
}
} catch (JSONException e) {
Log.e(TAG, e.toString());// 记录异常信息到日志
e.printStackTrace();// 打印异常堆栈信息
}
}
/**
* 从内容中获取本地JSON对象
* @return 本地JSON对象
*/
public JSONObject getLocalJSONFromContent() {
String name = getName();// 获取任务名称
try { // 如果mMetaInfo为空表示是新从网页创建的任务
if (mMetaInfo == null) {
// new task created from web
if (name == null) {// 如果任务名称为空
Log.w(TAG, "the note seems to be an empty one"); // 记录警告信息到日志
return null;// 返回null
}
JSONObject js = new JSONObject();// 创建新的JSONObject
JSONObject note = new JSONObject(); // 创建note部分的JSONObject
JSONArray dataArray = new JSONArray();// 创建data部分的JSONArray
JSONObject data = new JSONObject(); // 创建data部分的JSONObject
data.put(DataColumns.CONTENT, name); // 将任务名称放入data
dataArray.put(data); // 将data放入dataArray
js.put(GTaskStringUtils.META_HEAD_DATA, dataArray); // 将dataArray放入js
note.put(NoteColumns.TYPE, Notes.TYPE_NOTE);// 设置note的类型
js.put(GTaskStringUtils.META_HEAD_NOTE, note);// 将note放入js
return js;// 返回创建的JSON对象
} else {
// synced task // 如果mMetaInfo不为空表示是已同步的任务
JSONObject note = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
// 获取已同步任务的data部分
JSONArray dataArray = mMetaInfo.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
// 遍历dataArray数组
for (int i = 0; i < dataArray.length(); i++) {
JSONObject data = dataArray.getJSONObject(i);// 获取数组中的每个JSONObject
// 如果数据类型是笔记
if (TextUtils.equals(data.getString(DataColumns.MIME_TYPE), DataConstants.NOTE)) {
data.put(DataColumns.CONTENT, getName());// 更新笔记内容
break; // 找到匹配的数据后跳出循环
}
}
// 更新note的类型
note.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
return mMetaInfo; // 返回更新后的mMetaInfo
}
} catch (JSONException e) {
Log.e(TAG, e.toString()); // 记录异常信息到日志
e.printStackTrace();// 打印异常堆栈信息
return null;// 发生异常时返回null
}
}
/**
* 设置元数据信息
* @param metaData 元数据对象
*/
public void setMetaInfo(MetaData metaData) {
if (metaData != null && metaData.getNotes() != null) { // 如果元数据对象不为空且包含笔记信息
try {
mMetaInfo = new JSONObject(metaData.getNotes()); // 将笔记信息转换为JSONObject
} catch (JSONException e) {
Log.w(TAG, e.toString()); // 记录警告信息到日志
mMetaInfo = null;// 发生异常时将mMetaInfo设置为null
}
}
}
/**
* 获取同步操作类型
* @param c 数据库游标
* @return 同步操作类型
*/
public int getSyncAction(Cursor c) {
try {
JSONObject noteInfo = null; // 如果mMetaInfo不为空并且包含
if (mMetaInfo != null && mMetaInfo.has(GTaskStringUtils.META_HEAD_NOTE)) {
noteInfo = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
}
// 如果noteInfo为空表示笔记元数据可能已被删除
if (noteInfo == null) {
Log.w(TAG, "it seems that note meta has been deleted");
return SYNC_ACTION_UPDATE_REMOTE;// 需要更新远程数据
}
// 如果noteInfo不包含ID字段表示远程笔记ID可能已被删除
if (!noteInfo.has(NoteColumns.ID)) {
Log.w(TAG, "remote note id seems to be deleted");
return SYNC_ACTION_UPDATE_LOCAL; // 需要更新本地数据
}
// validate the note id now // 验证笔记ID是否匹配
if (c.getLong(SqlNote.ID_COLUMN) != noteInfo.getLong(NoteColumns.ID)) {
Log.w(TAG, "note id doesn't match");
return SYNC_ACTION_UPDATE_LOCAL;// 笔记ID不匹配需要更新本地数据
}
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 // 验证gtask id是否匹配
if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) {
Log.e(TAG, "gtask id doesn't match");
return SYNC_ACTION_ERROR;// gtask id不匹配同步错误
} // 如果本地修改时间等于远程最后修改时间,则只需更新远程
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
// local modification only
return SYNC_ACTION_UPDATE_REMOTE;// 只需更新远程
} else { // 存在冲突,需要解决冲突
return SYNC_ACTION_UPDATE_CONFLICT;
}
}
} catch (Exception e) {
Log.e(TAG, e.toString());// 记录异常信息到日志
e.printStackTrace();// 打印异常堆栈信息
}
return SYNC_ACTION_ERROR; // 如果发生异常,返回同步错误
}
/**
* 判断任务是否值得保存
* @return 如果元信息不为空或者任务名称不为空且长度大于0或者任务备注不为空且长度大于0则返回true
*/
public boolean isWorthSaving() {
return mMetaInfo != null || (getName() != null && getName().trim().length() > 0)
|| (getNotes() != null && getNotes().trim().length() > 0);
}
/**
* 设置任务是否完成
* @param completed 是否完成的标志
*/
public void setCompleted(boolean completed) {
this.mCompleted = completed;
}
/**
* 设置任务备注
* @param notes 任务备注
*/
public void setNotes(String notes) {
this.mNotes = notes;
}
/**
* 设置前一个兄弟任务
* @param priorSibling 前一个兄弟任务
*/
public void setPriorSibling(Task priorSibling) {
this.mPriorSibling = priorSibling;
}
/**
* 设置父任务列表
* @param parent 父任务列表
*/
public void setParent(TaskList parent) {
this.mParent = parent;
}
/**
* 获取任务是否完成的标志
* @return 是否完成
*/
public boolean getCompleted() {
return this.mCompleted;
}
/**
* 获取任务备注
* @return 任务备注
*/
public String getNotes() {
return this.mNotes;
}
/**
* 获取前一个兄弟任务
* @return 前一个兄弟任务
*/
public Task getPriorSibling() {
return this.mPriorSibling;
}
/**
* 获取父任务列表
* @return 父任务列表
*/
public TaskList getParent() {
return this.mParent;
}
}