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.
read/src/net/micode/notes/gtask/data/SqlNote改.java

466 lines
24 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.appwidget.AppWidgetManager; // 用于处理小部件
import android.content.ContentResolver; // 用于内容解析的类
import android.content.ContentValues; // 用于存储内容的类
import android.content.Context; // Android上下文类
import android.database.Cursor; // 数据库操作的游标类
import android.net.Uri; // URI的类
import android.util.Log; // 日志记录类
// 导入笔记和相关数据的类
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.gtask.exception.ActionFailureException; // 自定义异常类
import net.micode.notes.tool.GTaskStringUtils; // 字符串工具类
import net.micode.notes.tool.ResourceParser; // 资源解析工具类
import org.json.JSONArray; // JSON数组类
import org.json.JSONException; // JSON异常类
import org.json.JSONObject; // JSON对象类
import java.util.ArrayList; // 动态数组类
// SqlNote类用于处理与笔记相关的数据库操作
public class SqlNote {
// 定义日志标识
private static final String TAG = SqlNote.class.getSimpleName();
// 定义无效ID常量
private static final int INVALID_ID = -99999;
// 定义用于查询的数据列投影
public static final String[] PROJECTION_NOTE = new String[] {
NoteColumns.ID, NoteColumns.ALERTED_DATE, NoteColumns.BG_COLOR_ID,
NoteColumns.CREATED_DATE, NoteColumns.HAS_ATTACHMENT, NoteColumns.MODIFIED_DATE,
NoteColumns.NOTES_COUNT, NoteColumns.PARENT_ID, NoteColumns.SNIPPET, NoteColumns.TYPE,
NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE, NoteColumns.SYNC_ID,
NoteColumns.LOCAL_MODIFIED, NoteColumns.ORIGIN_PARENT_ID, NoteColumns.GTASK_ID,
NoteColumns.VERSION
};
// 定义数据列在投影中的索引
public static final int ID_COLUMN = 0; // ID列索引
public static final int ALERTED_DATE_COLUMN = 1; // 提醒日期列索引
public static final int BG_COLOR_ID_COLUMN = 2; // 背景颜色ID列索引
public static final int CREATED_DATE_COLUMN = 3; // 创建日期列索引
public static final int HAS_ATTACHMENT_COLUMN = 4; // 是否有附件列索引
public static final int MODIFIED_DATE_COLUMN = 5; // 修改日期列索引
public static final int NOTES_COUNT_COLUMN = 6; // 笔记数量列索引
public static final int PARENT_ID_COLUMN = 7; // 父级ID列索引
public static final int SNIPPET_COLUMN = 8; // 摘要列索引
public static final int TYPE_COLUMN = 9; // 类型列索引
public static final int WIDGET_ID_COLUMN = 10; // 小部件ID列索引
public static final int WIDGET_TYPE_COLUMN = 11; // 小部件类型列索引
public static final int SYNC_ID_COLUMN = 12; // 同步ID列索引
public static final int LOCAL_MODIFIED_COLUMN = 13; // 本地修改时间列索引
public static final int ORIGIN_PARENT_ID_COLUMN = 14; // 原始父级ID列索引
public static final int GTASK_ID_COLUMN = 15; // GTask ID列索引
public static final int VERSION_COLUMN = 16; // 版本列索引
// 定义成员变量
private Context mContext; // 上下文
private ContentResolver mContentResolver; // 内容解析器
private boolean mIsCreate; // 是否为创建状态
private long mId; // 笔记ID
private long mAlertDate; // 提醒日期
private int mBgColorId; // 背景颜色ID
private long mCreatedDate; // 创建日期
private int mHasAttachment; // 是否有附件
private long mModifiedDate; // 修改日期
private long mParentId; // 父级ID
private String mSnippet; // 摘要
private int mType; // 类型
private int mWidgetId; // 小部件ID
private int mWidgetType; // 小部件类型
private long mOriginParent; // 原始父级ID
private long mVersion; // 版本
private ContentValues mDiffNoteValues; // 存储差异数据的ContentValues
private ArrayList<SqlData> mDataList; // 存储数据列表
// 构造函数,用于创建新笔记
public SqlNote(Context context) {
mContext = context; // 保存上下文
mContentResolver = context.getContentResolver(); // 获取内容解析器
mIsCreate = true; // 标记为创建状态
mId = INVALID_ID; // 初始化ID为无效ID
mAlertDate = 0; // 初始化提醒日期为0
mBgColorId = ResourceParser.getDefaultBgId(context); // 获取默认背景颜色ID
mCreatedDate = System.currentTimeMillis(); // 获取当前时间作为创建日期
mHasAttachment = 0; // 初始化无附件
mModifiedDate = System.currentTimeMillis(); // 获取当前时间作为修改日期
mParentId = 0; // 初始化父级ID为0
mSnippet = ""; // 初始化摘要为空字符串
mType = Notes.TYPE_NOTE; // 设置默认类型为笔记
mWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID; // 默认无效小部件ID
mWidgetType = Notes.TYPE_WIDGET_INVALIDE; // 设置无效小部件类型
mOriginParent = 0; // 初始化原始父级ID为0
mVersion = 0; // 初始化版本为0
mDiffNoteValues = new ContentValues(); // 创建新的差异数据ContentValues
mDataList = new ArrayList<SqlData>(); // 创建新的数据列表
}
// 构造函数用于从Cursor中加载现有笔记
public SqlNote(Context context, Cursor c) {
mContext = context; // 保存上下文
mContentResolver = context.getContentResolver(); // 获取内容解析器
mIsCreate = false; // 标记为非创建状态
loadFromCursor(c); // 从Cursor加载数据
mDataList = new ArrayList<SqlData>(); // 创建新的数据列表
if (mType == Notes.TYPE_NOTE) // 如果类型为笔记
loadDataContent(); // 加载数据内容
mDiffNoteValues = new ContentValues(); // 创建新的差异数据ContentValues
}
// 构造函数用于根据ID加载笔记
public SqlNote(Context context, long id) {
mContext = context; // 保存上下文
mContentResolver = context.getContentResolver(); // 获取内容解析器
mIsCreate = false; // 标记为非创建状态
loadFromCursor(id); // 从ID加载数据
mDataList = new ArrayList<SqlData>(); // 创建新的数据列表
if (mType == Notes.TYPE_NOTE) // 如果类型为笔记
loadDataContent(); // 加载数据内容
mDiffNoteValues = new ContentValues(); // 创建新的差异数据ContentValues
}
// 从Cursor根据ID加载数据
private void loadFromCursor(long id) {
Cursor c = null; // 游标初始化
try {
// 查询笔记数据
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, PROJECTION_NOTE, "(_id=?)",
new String[] { String.valueOf(id) }, null);
if (c != null) { // 如果游标不为空
c.moveToNext(); // 移动到下一条记录
loadFromCursor(c); // 从Cursor加载数据
} else {
Log.w(TAG, "loadFromCursor: cursor = null"); // 日志输出
}
} finally {
if (c != null) // 如果游标不为空
c.close(); // 关闭游标
}
}
// 从Cursor加载数据
private void loadFromCursor(Cursor c) {
mId = c.getLong(ID_COLUMN); // 获取ID
mAlertDate = c.getLong(ALERTED_DATE_COLUMN); // 获取提醒日期
mBgColorId = c.getInt(BG_COLOR_ID_COLUMN); // 获取背景颜色ID
mCreatedDate = c.getLong(CREATED_DATE_COLUMN); // 获取创建日期
mHasAttachment = c.getInt(HAS_ATTACHMENT_COLUMN); // 获取是否有附件
mModifiedDate = c.getLong(MODIFIED_DATE_COLUMN); // 获取修改日期
mParentId = c.getLong(PARENT_ID_COLUMN); // 获取父级ID
mSnippet = c.getString(SNIPPET_COLUMN); // 获取摘要
mType = c.getInt(TYPE_COLUMN); // 获取类型
mWidgetId = c.getInt(WIDGET_ID_COLUMN); // 获取小部件ID
mWidgetType = c.getInt(WIDGET_TYPE_COLUMN); // 获取小部件类型
mVersion = c.getLong(VERSION_COLUMN); // 获取版本
}
// 加载数据内容
private void loadDataContent() {
Cursor c = null; // 游标初始化
mDataList.clear(); // 清空数据列表
try {
// 查询数据内容
c = mContentResolver.query(Notes.CONTENT_DATA_URI, SqlData.PROJECTION_DATA,
"(note_id=?)", new String[] { String.valueOf(mId) }, null);
if (c != null) { // 如果游标不为空
if (c.getCount() == 0) { // 如果没有数据
Log.w(TAG, "it seems that the note has not data"); // 日志输出
return; // 退出方法
}
while (c.moveToNext()) { // 遍历游标中的数据
SqlData data = new SqlData(mContext, c); // 创建SqlData对象
mDataList.add(data); // 添加到数据列表
}
} else {
Log.w(TAG, "loadDataContent: cursor = null"); // 日志输出
}
} finally {
if (c != null) // 如果游标不为空
c.close(); // 关闭游标
}
}
// 设置笔记内容
public boolean setContent(JSONObject js) {
try {
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); // 获取笔记对象
if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) { // 如果是系统文件夹
Log.w(TAG, "cannot set system folder"); // 日志输出
} else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) { // 如果是文件夹
// 仅更新摘要和类型
String snippet = note.has(NoteColumns.SNIPPET) ? note.getString(NoteColumns.SNIPPET) : ""; // 获取摘要
if (mIsCreate || !mSnippet.equals(snippet)) { // 如果是创建状态或摘要不相同
mDiffNoteValues.put(NoteColumns.SNIPPET, snippet); // 存储摘要
}
mSnippet = snippet; // 更新摘要
int type = note.has(NoteColumns.TYPE) ? note.getInt(NoteColumns.TYPE) : Notes.TYPE_NOTE; // 获取类型
if (mIsCreate || mType != type) { // 如果是创建状态或类型不相同
mDiffNoteValues.put(NoteColumns.TYPE, type); // 存储类型
}
mType = type; // 更新类型
} else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_NOTE) { // 如果是笔记
JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA); // 获取数据数组
long id = note.has(NoteColumns.ID) ? note.getLong(NoteColumns.ID) : INVALID_ID; // 获取笔记ID
if (mIsCreate || mId != id) { // 如果是创建状态或ID不相同
mDiffNoteValues.put(NoteColumns.ID, id); // 存储笔记ID
}
mId = id; // 更新ID
long alertDate = note.has(NoteColumns.ALERTED_DATE) ? note.getLong(NoteColumns.ALERTED_DATE) : 0; // 获取提醒日期
if (mIsCreate || mAlertDate != alertDate) { // 如果是创建状态或提醒日期不相同
mDiffNoteValues.put(NoteColumns.ALERTED_DATE, alertDate); // 存储提醒日期
}
mAlertDate = alertDate; // 更新提醒日期
int bgColorId = note.has(NoteColumns.BG_COLOR_ID) ? note.getInt(NoteColumns.BG_COLOR_ID) : ResourceParser.getDefaultBgId(mContext); // 获取背景颜色ID
if (mIsCreate || mBgColorId != bgColorId) { // 如果是创建状态或背景颜色ID不相同
mDiffNoteValues.put(NoteColumns.BG_COLOR_ID, bgColorId); // 存储背景颜色ID
}
mBgColorId = bgColorId; // 更新背景颜色ID
long createDate = note.has(NoteColumns.CREATED_DATE) ? note.getLong(NoteColumns.CREATED_DATE) : System.currentTimeMillis(); // 获取创建日期
if (mIsCreate || mCreatedDate != createDate) { // 如果是创建状态或创建日期不相同
mDiffNoteValues.put(NoteColumns.CREATED_DATE, createDate); // 存储创建日期
}
mCreatedDate = createDate; // 更新创建日期
int hasAttachment = note.has(NoteColumns.HAS_ATTACHMENT) ? note.getInt(NoteColumns.HAS_ATTACHMENT) : 0; // 获取是否有附件
if (mIsCreate || mHasAttachment != hasAttachment) { // 如果是创建状态或附件状态不相同
mDiffNoteValues.put(NoteColumns.HAS_ATTACHMENT, hasAttachment); // 存储附件状态
}
mHasAttachment = hasAttachment; // 更新附件状态
long modifiedDate = note.has(NoteColumns.MODIFIED_DATE) ? note.getLong(NoteColumns.MODIFIED_DATE) : System.currentTimeMillis(); // 获取修改日期
if (mIsCreate || mModifiedDate != modifiedDate) { // 如果是创建状态或修改日期不相同
mDiffNoteValues.put(NoteColumns.MODIFIED_DATE, modifiedDate); // 存储修改日期
}
mModifiedDate = modifiedDate; // 更新修改日期
long parentId = note.has(NoteColumns.PARENT_ID) ? note.getLong(NoteColumns.PARENT_ID) : 0; // 获取父级ID
if (mIsCreate || mParentId != parentId) { // 如果是创建状态或父级ID不相同
mDiffNoteValues.put(NoteColumns.PARENT_ID, parentId); // 存储父级ID
}
mParentId = parentId; // 更新父级ID
String snippet = note.has(NoteColumns.SNIPPET) ? note.getString(NoteColumns.SNIPPET) : ""; // 获取摘要
if (mIsCreate || !mSnippet.equals(snippet)) { // 如果是创建状态或摘要不相同
mDiffNoteValues.put(NoteColumns.SNIPPET, snippet); // 存储摘要
}
mSnippet = snippet; // 更新摘要
int type = note.has(NoteColumns.TYPE) ? note.getInt(NoteColumns.TYPE) : Notes.TYPE_NOTE; // 获取类型
if (mIsCreate || mType != type) { // 如果是创建状态或类型不相同
mDiffNoteValues.put(NoteColumns.TYPE, type); // 存储类型
}
mType = type; // 更新类型
int widgetId = note.has(NoteColumns.WIDGET_ID) ? note.getInt(NoteColumns.WIDGET_ID) : AppWidgetManager.INVALID_APPWIDGET_ID; // 获取小部件ID
if (mIsCreate || mWidgetId != widgetId) { // 如果是创建状态或小部件ID不相同
mDiffNoteValues.put(NoteColumns.WIDGET_ID, widgetId); // 存储小部件ID
}
mWidgetId = widgetId; // 更新小部件ID
int widgetType = note.has(NoteColumns.WIDGET_TYPE) ? note.getInt(NoteColumns.WIDGET_TYPE) : Notes.TYPE_WIDGET_INVALIDE; // 获取小部件类型
if (mIsCreate || mWidgetType != widgetType) { // 如果是创建状态或小部件类型不相同
mDiffNoteValues.put(NoteColumns.WIDGET_TYPE, widgetType); // 存储小部件类型
}
mWidgetType = widgetType; // 更新小部件类型
long originParent = note.has(NoteColumns.ORIGIN_PARENT_ID) ? note.getLong(NoteColumns.ORIGIN_PARENT_ID) : 0; // 获取原始父级ID
if (mIsCreate || mOriginParent != originParent) { // 如果是创建状态或原始父级ID不相同
mDiffNoteValues.put(NoteColumns.ORIGIN_PARENT_ID, originParent); // 存储原始父级ID
}
mOriginParent = originParent; // 更新原始父级ID
// 略微省略到此
// 后续操作,涉及其他数据处理
}
} catch (JSONException e) { // 处理JSON解析异常
Log.e(TAG, e.toString()); // 输出异常信息
e.printStackTrace(); // 打印堆栈信息
return false; // 返回设置失败
}
return true; // 返回设置成功
}
// 获取笔记内容的方法
public JSONObject getContent() {
try {
JSONObject js = new JSONObject(); // 创建一个新的JSON对象
if (mIsCreate) { // 如果是创建状态
Log.e(TAG, "it seems that we haven't created this in database yet"); // 日志输出
return null; // 返回null因为还没有在数据库中创建
}
JSONObject note = new JSONObject(); // 创建笔记对象
if (mType == Notes.TYPE_NOTE) { // 如果笔记类型是普通笔记
note.put(NoteColumns.ID, mId); // 设置ID
note.put(NoteColumns.ALERTED_DATE, mAlertDate); // 设置提醒日期
note.put(NoteColumns.BG_COLOR_ID, mBgColorId); // 设置背景颜色ID
note.put(NoteColumns.CREATED_DATE, mCreatedDate); // 设置创建日期
note.put(NoteColumns.HAS_ATTACHMENT, mHasAttachment); // 设置是否有附件
note.put(NoteColumns.MODIFIED_DATE, mModifiedDate); // 设置修改日期
note.put(NoteColumns.PARENT_ID, mParentId); // 设置父级ID
note.put(NoteColumns.SNIPPET, mSnippet); // 设置摘要
note.put(NoteColumns.TYPE, mType); // 设置类型
note.put(NoteColumns.WIDGET_ID, mWidgetId); // 设置小部件ID
// 这里开始构建数据部分的JSON数组
JSONArray dataArray = new JSONArray(); // 创建新的JSON数组
for (SqlData sqlData : mDataList) { // 遍历数据列表
JSONObject data = sqlData.getContent(); // 获取每个SqlData对象的内容
if (data != null) { // 如果数据不为空
dataArray.put(data); // 将数据添加到数组中
}
}
js.put(GTaskStringUtils.META_HEAD_DATA, dataArray); // 将数据数组添加到主JSON对象中
} else if (mType == Notes.TYPE_FOLDER || mType == Notes.TYPE_SYSTEM) { // 如果类型为文件夹或系统文件夹
note.put(NoteColumns.ID, mId); // 设置ID
note.put(NoteColumns.TYPE, mType); // 设置类型
note.put(NoteColumns.SNIPPET, mSnippet); // 设置摘要
js.put(GTaskStringUtils.META_HEAD_NOTE, note); // 将笔记对象添加到主JSON对象中
}
return js; // 返回最终构建的JSON对象
} catch (JSONException e) { // 捕获JSON异常
Log.e(TAG, e.toString()); // 日志输出异常信息
e.printStackTrace(); // 打印堆栈信息
}
return null; // 如果发生异常则返回null
}
// 设置父级ID的方法
public void setParentId(long id) {
mParentId = id; // 更新父级ID
mDiffNoteValues.put(NoteColumns.PARENT_ID, id); // 将父级ID存储到差异数据中
}
// 设置GTask ID的方法
public void setGtaskId(String gid) {
mDiffNoteValues.put(NoteColumns.GTASK_ID, gid); // 将GTask ID存储到差异数据中
}
// 设置同步ID的方法
public void setSyncId(long syncId) {
mDiffNoteValues.put(NoteColumns.SYNC_ID, syncId); // 将同步ID存储到差异数据中
}
// 重置本地修改时间的方法
public void resetLocalModified() {
mDiffNoteValues.put(NoteColumns.LOCAL_MODIFIED, 0); // 将本地修改时间设置为0
}
// 获取笔记ID的方法
public long getId() {
return mId; // 返回ID
}
// 获取父级ID的方法
public long getParentId() {
return mParentId; // 返回父级ID
}
// 获取摘要的方法
public String getSnippet() {
return mSnippet; // 返回摘要
}
// 判断是否为笔记类型的方法
public boolean isNoteType() {
return mType == Notes.TYPE_NOTE; // 如果类型为笔记返回true否则返回false
}
// 提交数据的方法
public void commit(boolean validateVersion) {
if (mIsCreate) { // 如果是创建状态
if (mId == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) {
mDiffNoteValues.remove(NoteColumns.ID); // 如果ID为无效ID且包含ID则移除
}
Uri uri = mContentResolver.insert(Notes.CONTENT_NOTE_URI, mDiffNoteValues); // 插入数据
try {
mId = Long.valueOf(uri.getPathSegments().get(1)); // 获取新插入数据的ID
} catch (NumberFormatException e) {
Log.e(TAG, "Get note id error :" + e.toString()); // 打印错误日志
throw new ActionFailureException("create note failed"); // 抛出创建失败异常
}
if (mId == 0) {
throw new IllegalStateException("Create thread id failed"); // 检查ID是否有效
}
if (mType == Notes.TYPE_NOTE) { // 如果类型为笔记
for (SqlData sqlData : mDataList) { // 遍历数据列表
sqlData.commit(mId, false, -1); // 提交每个SqlData对象
}
}
} else { // 如果不是创建状态
if (mId <= 0 && mId != Notes.ID_ROOT_FOLDER && mId != Notes.ID_CALL_RECORD_FOLDER) {
Log.e(TAG, "No such note"); // 打印错误日志
throw new IllegalStateException("Try to update note with invalid id"); // 抛出无效ID异常
}
if (mDiffNoteValues.size() > 0) { // 如果存在差异数据
mVersion++; // 增加版本号
int result = 0; // 结果计数器
if (!validateVersion) { // 如果不需要验证版本
// 根据笔记ID更新数据
result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "("
+ NoteColumns.ID + "=?)", new String[] {
String.valueOf(mId)
});
} else { // 如果需要验证版本
// 根据版本验证更新数据
result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "("
+ NoteColumns.ID + "=?) AND (" + NoteColumns.VERSION + "<=?)",
new String[] {
String.valueOf(mId), String.valueOf(mVersion)
});
}
if (result == 0) {
Log.w(TAG, "there is no update. maybe user updates note when syncing"); // 日志输出
}
}
if (mType == Notes.TYPE_NOTE) { // 如果类型为笔记
for (SqlData sqlData : mDataList) { // 遍历数据列表
sqlData.commit(mId, validateVersion, mVersion); // 提交每个SqlData对象
}
}
}
// 刷新本地信息
loadFromCursor(mId); // 根据ID加载数据
if (mType == Notes.TYPE_NOTE) // 如果类型为笔记
loadDataContent(); // 加载数据内容
mDiffNoteValues.clear(); // 清空差异数据
mIsCreate = false; // 设置为非创建状态
}
}