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.

350 lines
16 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;
import android.database.Cursor;
import android.net.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;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
// SqlNote类用于处理与SQL数据库中笔记相关的数据操作包括创建、读取、更新和提交笔记数据
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
};
// 定义ID列在投影列数组中的索引
public static final int ID_COLUMN = 0;
// 定义提醒日期列在投影列数组中的索引
public static final int ALERTED_DATE_COLUMN = 1;
// 定义背景颜色ID列在投影列数组中的索引
public static final int BG_COLOR_ID_COLUMN = 2;
// 定义创建日期列在投影列数组中的索引
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;
// 定义父ID列在投影列数组中的索引
public static final int PARENT_ID_COLUMN = 7;
// 定义片段列在投影列数组中的索引(可能是笔记的简短描述等)
public static final int SNIPPET_COLUMN = 8;
// 定义类型列在投影列数组中的索引(如笔记类型、文件夹类型等)
public static final int TYPE_COLUMN = 9;
// 定义小部件ID列在投影列数组中的索引
public static final int WIDGET_ID_COLUMN = 10;
// 定义小部件类型列在投影列数组中的索引
public static final int WIDGET_TYPE_COLUMN = 11;
// 定义同步ID列在投影列数组中的索引
public static final int SYNC_ID_COLUMN = 12;
// 定义本地修改列在投影列数组中的索引
public static final int LOCAL_MODIFIED_COLUMN = 13;
// 定义原始父ID列在投影列数组中的索引根据上下文可能有不同用途
public static final int ORIGIN_PARENT_ID_COLUMN = 14;
// 定义GTask ID列在投影列数组中的索引可能与特定任务系统相关
public static final int GTASK_ID_COLUMN = 15;
// 定义版本列在投影列数组中的索引
public static final int VERSION_COLUMN = 16;
// 应用程序上下文
private Context mContext;
// 用于与内容提供器进行交互,以访问和操作数据
private ContentResolver mContentResolver;
// 表示是否为创建操作
private boolean mIsCreate;
// 笔记的ID
private long mId;
// 笔记的提醒日期
private long mAlertDate;
// 笔记的背景颜色ID
private int mBgColorId;
// 笔记的创建日期
private long mCreatedDate;
// 表示笔记是否有附件
private int mHasAttachment;
// 笔记的修改日期
private long mModifiedDate;
// 笔记的父ID
private long mParentId;
// 笔记的片段(可能是简短描述等)
private String mSnippet;
// 笔记的类型
private int mType;
// 笔记关联的小部件ID
private int mWidgetId;
// 笔记关联的小部件类型
private int mWidgetType;
// 笔记的原始父ID根据上下文可能有不同用途
private long mOriginParent;
// 笔记的版本号
private long mVersion;
// 用于存储要更新的笔记数据值
private ContentValues mDiffNoteValues;
// 存储与笔记相关的数据列表(可能是笔记的内容数据等)
private ArrayList<SqlData> mDataList;
// 构造函数用于创建一个新的SqlNote实例通常用于插入新笔记
public SqlNote(Context context) {
mContext = context;
mContentResolver = context.getContentResolver();
mIsCreate = true;
mId = INVALID_ID;
mAlertDate = 0;
// 获取默认的背景颜色ID
mBgColorId = ResourceParser.getDefaultBgId(context);
mCreatedDate = System.currentTimeMillis();
mHasAttachment = 0;
mModifiedDate = System.currentTimeMillis();
mParentId = 0;
mSnippet = "";
mType = Notes.TYPE_NOTE;
mWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
mWidgetType = Notes.TYPE_WIDGET_INVALIDE;
mOriginParent = 0;
mVersion = 0;
mDiffNoteValues = new ContentValues();
mDataList = new ArrayList<SqlData>();
}
// 构造函数用于根据数据库游标创建一个SqlNote实例通常用于读取现有笔记
public SqlNote(Context context, Cursor c) {
mContext = context;
mContentResolver = context.getContentResolver();
mIsCreate = false;
loadFromCursor(c);
mDataList = new ArrayList<SqlData>();
if (mType == Notes.TYPE_NOTE)
loadDataContent();
mDiffNoteValues = new ContentValues();
}
// 构造函数根据指定的ID从数据库加载笔记数据创建SqlNote实例
public SqlNote(Context context, long id) {
mContext = context;
mContentResolver = context.getContentResolver();
mIsCreate = false;
loadFromCursor(id);
mDataList = new ArrayList<SqlData>();
if (mType == Notes.TYPE_NOTE)
loadDataContent();
mDiffNoteValues = new ContentValues();
}
// 根据ID从数据库加载笔记数据到当前实例的属性中
private void loadFromCursor(long id) {
Cursor c = null;
try {
// 查询指定ID的笔记数据
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, PROJECTION_NOTE, "(_id=?)",
new String[] { String.valueOf(id) }, null);
if (c!= null) {
c.moveToNext();
loadFromCursor(c);
} else {
Log.w(TAG, "loadFromCursor: cursor = null");
}
} finally {
if (c!= null)
c.close();
}
}
// 从数据库游标加载笔记数据到当前实例的属性中
private void loadFromCursor(Cursor c) {
mId = c.getLong(ID_COLUMN);
mAlertDate = c.getLong(ALERTED_DATE_COLUMN);
mBgColorId = c.getInt(BG_COLOR_ID_COLUMN);
mCreatedDate = c.getLong(CREATED_DATE_COLUMN);
mHasAttachment = c.getInt(HAS_ATTACHMENT_COLUMN);
mModifiedDate = c.getLong(MODIFIED_DATE_COLUMN);
mParentId = c.getLong(PARENT_ID_COLUMN);
mSnippet = c.getString(SNIPPET_COLUMN);
mType = c.getInt(TYPE_COLUMN);
mWidgetId = c.getInt(WIDGET_ID_COLUMN);
mWidgetType = c.getInt(WIDGET_TYPE_COLUMN);
mVersion = c.getLong(VERSION_COLUMN);
}
// 加载与笔记相关的数据内容(如果笔记类型为普通笔记)
private void loadDataContent() {
Cursor c = null;
mDataList.clear();
try {
// 查询与当前笔记ID相关的数据
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实例并添加到数据列表中
SqlData data = new SqlData(mContext, c);
mDataList.add(data);
}
} else {
Log.w(TAG, "loadDataContent: cursor = null");
}
} finally {
if (c!= null)
c.close();
}
}
// 设置笔记内容根据JSON对象中的数据更新本地笔记数据并记录数据差异
public boolean setContent(JSONObject js) {
try {
// 从JSON对象中获取笔记的元数据部分
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;
if (mIsCreate || mId!= id) {
mDiffNoteValues.put(NoteColumns.ID, id);
}
mId = 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);
if (mIsCreate || mBgColorId!= bgColorId) {
mDiffNoteValues.put(NoteColumns.BG_COLOR_ID, bgColorId);
}
mBgColorId = bgColorId;
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;
if (mIsCreate || mParentId!= parentId) {
mDiffNoteValues.put(NoteColumns.PARENT_ID, parentId);
}
mParentId = parentId;
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;
if (mIsCreate || mWidgetId!= widgetId) {
mDiffNoteValues.put(NoteColumns.WIDGET_ID, widgetId);
}
mWidgetId = widgetId;
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;
if (mIsCreate || mOriginParent!= originParent) {
mDiffNoteValues.put(NoteColumns.ORIGIN_PARENT_ID, originParent);
}
mOriginParent = originParent;
for (int i = 0; i < dataArray.length(); i++) {
JSONObject data = dataArray.getJSONObject(i);
SqlData sqlData = null;
if (data.has(DataColumns.ID)) {
long dataId = data.getLong(DataColumns.ID);
for (SqlData temp : mDataList) {
if (dataId == temp.getId()) {
sqlData = temp;
}
}
}
if (sqlData == null) {
sqlData = new SqlData(mContext);
mDataList.add(sqlData);
}
sqlData.setContent(data);
}
}
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
return false;
}
return true;
}
// 获取笔记内容以JSON对象形式返回如果是创建操作则返回null并记录错误日志
public JSONObject getContent() {
try {
JSONObject js = new JSONObject();
if (mIsCreate) {
Log.e(TAG, "it seems that we haven't created this in database yet");
return null;
}
JSONObject note = new JSONObject();
if (mType == Notes.TYPE_NOTE