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.
MiNote/gtask/data/Task.java

395 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.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;
/**
* 任务类继承自Node基类表示Google任务中的一个具体任务
* 处理任务的创建、更新、同步以及与本地数据库的交互
*/
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对象
* @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, mParent.getChildTaskIndex(this));
// 构建任务实体数据
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_TASK); // 实体类型为任务
if (getNotes() != null) {
entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes()); // 任务备注
}
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
// 设置父任务列表ID
js.put(GTaskStringUtils.GTASK_JSON_PARENT_ID, mParent.getGid());
// 设置父类型为组
js.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT_TYPE,
GTaskStringUtils.GTASK_JSON_TYPE_GROUP);
// 设置列表ID
js.put(GTaskStringUtils.GTASK_JSON_LIST_ID, mParent.getGid());
// 设置前一个兄弟任务ID(用于排序)
if (mPriorSibling != null) {
js.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, mPriorSibling.getGid());
}
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("生成任务创建JSON对象失败");
}
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()); // 更新任务名称
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);
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("生成任务更新JSON对象失败");
}
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));
}
// 设置任务备注
if (js.has(GTaskStringUtils.GTASK_JSON_NOTES)) {
setNotes(js.getString(GTaskStringUtils.GTASK_JSON_NOTES));
}
// 设置删除状态
if (js.has(GTaskStringUtils.GTASK_JSON_DELETED)) {
setDeleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_DELETED));
}
// 设置完成状态
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("从JSON对象获取任务内容失败");
}
}
}
/**
* 从本地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: 无可用数据");
}
try {
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
// 验证笔记类型
if (note.getInt(NoteColumns.TYPE) != Notes.TYPE_NOTE) {
Log.e(TAG, "无效的类型");
return;
}
// 从数据数组中获取笔记内容
for (int i = 0; i < dataArray.length(); i++) {
JSONObject data = dataArray.getJSONObject(i);
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 {
if (mMetaInfo == null) {
// 从网页创建的新任务
if (name == null) {
Log.w(TAG, "笔记内容为空");
return null;
}
// 构建新的JSON结构
JSONObject js = new JSONObject();
JSONObject note = new JSONObject();
JSONArray dataArray = new JSONArray();
JSONObject data = new JSONObject();
data.put(DataColumns.CONTENT, name); // 设置笔记内容
dataArray.put(data);
js.put(GTaskStringUtils.META_HEAD_DATA, dataArray); // 数据部分
note.put(NoteColumns.TYPE, Notes.TYPE_NOTE); // 设置笔记类型
js.put(GTaskStringUtils.META_HEAD_NOTE, note); // 笔记元信息
return js;
} else {
// 已同步的任务
JSONObject note = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
JSONArray dataArray = mMetaInfo.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
// 更新笔记内容
for (int i = 0; i < dataArray.length(); i++) {
JSONObject data = dataArray.getJSONObject(i);
if (TextUtils.equals(data.getString(DataColumns.MIME_TYPE), DataConstants.NOTE)) {
data.put(DataColumns.CONTENT, getName());
break;
}
}
note.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
return mMetaInfo;
}
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
return null;
}
}
/**
* 设置元数据信息
* @param metaData 元数据对象
*/
public void setMetaInfo(MetaData metaData) {
if (metaData != null && metaData.getNotes() != null) {
try {
mMetaInfo = new JSONObject(metaData.getNotes()); // 从备注解析元数据
} catch (JSONException e) {
Log.w(TAG, e.toString());
mMetaInfo = null;
}
}
}
/**
* 获取同步动作类型
* @param c 数据库游标
* @return 同步动作类型常量
*/
public int getSyncAction(Cursor c) {
try {
JSONObject noteInfo = null;
if (mMetaInfo != null && mMetaInfo.has(GTaskStringUtils.META_HEAD_NOTE)) {
noteInfo = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
}
if (noteInfo == null) {
Log.w(TAG, "笔记元数据似乎已被删除");
return SYNC_ACTION_UPDATE_REMOTE; // 需要更新远程
}
if (!noteInfo.has(NoteColumns.ID)) {
Log.w(TAG, "远程笔记ID似乎已被删除");
return SYNC_ACTION_UPDATE_LOCAL; // 需要更新本地
}
// 验证笔记ID是否匹配
if (c.getLong(SqlNote.ID_COLUMN) != noteInfo.getLong(NoteColumns.ID)) {
Log.w(TAG, "笔记ID不匹配");
return SYNC_ACTION_UPDATE_LOCAL;
}
// 检查本地修改状态
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 {
// 验证任务ID
if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) {
Log.e(TAG, "任务ID不匹配");
return SYNC_ACTION_ERROR;
}
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
// 只有本地修改
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 如果有有效内容则返回true否则返回false
*/
public boolean isWorthSaving() {
return mMetaInfo != null || (getName() != null && getName().trim().length() > 0)
|| (getNotes() != null && getNotes().trim().length() > 0);
}
// 以下是getter和setter方法
public void setCompleted(boolean completed) {
this.mCompleted = completed;
}
public void setNotes(String notes) {
this.mNotes = notes;
}
public void setPriorSibling(Task priorSibling) {
this.mPriorSibling = priorSibling;
}
public void setParent(TaskList parent) {
this.mParent = parent;
}
public boolean getCompleted() {
return this.mCompleted;
}
public String getNotes() {
return this.mNotes;
}
public Task getPriorSibling() {
return this.mPriorSibling;
}
public TaskList getParent() {
return this.mParent;
}
}