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.
ReadMiNotes/标注/SqlNote.java

670 lines
25 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;
public class SqlNote {
private static final String TAG = SqlNote.class.getSimpleName();
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;
// 警报日期列
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;
// 任务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;
// 0 = no, 1 = yes
private int mHasAttachment;
// 0 = no, 1 = yes
private long mModifiedDate;
// parent id
private long mParentId;
// 160 characters max
private String mSnippet;
// 0 = note, 1 = task, 2 = both
private int mType;
// widget id
private int mWidgetId;
// widget type
private int mWidgetType;
// origin parent id
private long mOriginParent;
// version
private long mVersion;
private ContentValues mDiffNoteValues;
// 用于存储SqlData对象的列表
private ArrayList<SqlData> mDataList;
// 构造函数,传入上下文
// 创建SqlNote对象并初始化
public SqlNote(Context context) {
mContext = context;
//获取上下文
mContentResolver = context.getContentResolver();
//获取内容解析器
mIsCreate = true;
//是否创建
mId = INVALID_ID;
//ID
mAlertDate = 0;
//警报日期
mBgColorId = ResourceParser.getDefaultBgId(context);
//背景颜色ID
mCreatedDate = System.currentTimeMillis();
//创建日期
mHasAttachment = 0;
//是否有附件
mModifiedDate = System.currentTimeMillis();
//修改日期
mParentId = 0;
//父ID
mSnippet = "";
//摘要
mType = Notes.TYPE_NOTE;
//类型
mWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
//小部件ID
mWidgetType = Notes.TYPE_WIDGET_INVALIDE;
//小部件类型
mOriginParent = 0;
//来源父
mVersion = 0;
//版本
mDiffNoteValues = new ContentValues();
mDataList = new ArrayList<SqlData>();
}
// 创建SqlNote对象从Cursor中加载数据
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();
}
// 创建SqlNote对象传入上下文和id
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();
}
private void loadFromCursor(long id) {
Cursor c = null;
try {
// 根据id查询Notes表中的数据
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) {
// 从游标中获取ID
mId = c.getLong(ID_COLUMN);
// 从游标中获取提示日期
mAlertDate = c.getLong(ALERTED_DATE_COLUMN);
// 从游标中获取背景颜色ID
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);
// 从游标中获取父ID
mParentId = c.getLong(PARENT_ID_COLUMN);
// 从游标中获取摘要
mSnippet = c.getString(SNIPPET_COLUMN);
// 从游标中获取类型
mType = c.getInt(TYPE_COLUMN);
// 从游标中获取小部件ID
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 {
// 根据note_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 data = new SqlData(mContext, c);
mDataList.add(data);
}
} else {
Log.w(TAG, "loadDataContent: cursor = null");
}
} finally {
if (c != null)
c.close();
}
}
public boolean setContent(JSONObject js) {
try {
// 获取js中的meta_head_note对象
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
// 判断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) {
// 判断note的类型是否为文件夹
// for folder we can only update the snnipet and type
// 获取note中的snippet
String snippet = note.has(NoteColumns.SNIPPET) ? note
.getString(NoteColumns.SNIPPET) : "";
// 判断是否为创建或者mSnippet是否与note中的snippet不同
if (mIsCreate || !mSnippet.equals(snippet)) {
// 将mSnippet与note中的snippet进行比较不同的值放入mDiffNoteValues中
mDiffNoteValues.put(NoteColumns.SNIPPET, snippet);
}
// 将note中的snippet赋值给mSnippet
mSnippet = snippet;
// 获取note中的type
int type = note.has(NoteColumns.TYPE) ? note.getInt(NoteColumns.TYPE)
: Notes.TYPE_NOTE;
// 判断是否为创建或者mType是否与note中的type不同
if (mIsCreate || mType != type) {
// 将mType与note中的type进行比较不同的值放入mDiffNoteValues中
mDiffNoteValues.put(NoteColumns.TYPE, type);
}
// 将note中的type赋值给mType
mType = type;
} else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_NOTE) {
// 获取JSONArray类型的dataArray
JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
// 获取note中的id
long id = note.has(NoteColumns.ID) ? note.getLong(NoteColumns.ID) : INVALID_ID;
// 判断是否是创建操作或者mId和id不相等
if (mIsCreate || mId != id) {
mDiffNoteValues.put(NoteColumns.ID, id);
}
mId = id;
// 获取note中的alertDate
long alertDate = note.has(NoteColumns.ALERTED_DATE) ? note
.getLong(NoteColumns.ALERTED_DATE) : 0;
// 判断是否是创建操作或者mAlertDate和alertDate不相等
if (mIsCreate || mAlertDate != alertDate) {
mDiffNoteValues.put(NoteColumns.ALERTED_DATE, alertDate);
}
mAlertDate = alertDate;
// 获取note中的bgColorId
int bgColorId = note.has(NoteColumns.BG_COLOR_ID) ? note
.getInt(NoteColumns.BG_COLOR_ID) : ResourceParser.getDefaultBgId(mContext);
// 判断是否是创建操作或者mBgColorId和bgColorId不相等
if (mIsCreate || mBgColorId != bgColorId) {
mDiffNoteValues.put(NoteColumns.BG_COLOR_ID, bgColorId);
}
mBgColorId = bgColorId;
// 获取note中的createDate
long createDate = note.has(NoteColumns.CREATED_DATE) ? note
.getLong(NoteColumns.CREATED_DATE) : System.currentTimeMillis();
// 判断是否是创建操作或者mCreatedDate和createDate不相等
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;
// 获取父ID
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);
}
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;
// 获取note中的widgetId
int widgetId = note.has(NoteColumns.WIDGET_ID) ? note.getInt(NoteColumns.WIDGET_ID)
: AppWidgetManager.INVALID_APPWIDGET_ID;
// 如果mIsCreate为true或者mWidgetId不等于widgetId则将widgetId添加到mDiffNoteValues中
if (mIsCreate || mWidgetId != widgetId) {
mDiffNoteValues.put(NoteColumns.WIDGET_ID, widgetId);
}
// 将widgetId赋值给mWidgetId
mWidgetId = widgetId;
// 获取note中的widgetType
int widgetType = note.has(NoteColumns.WIDGET_TYPE) ? note
.getInt(NoteColumns.WIDGET_TYPE) : Notes.TYPE_WIDGET_INVALIDE;
// 如果mIsCreate为true或者mWidgetType不等于widgetType则将widgetType添加到mDiffNoteValues中
if (mIsCreate || mWidgetType != widgetType) {
mDiffNoteValues.put(NoteColumns.WIDGET_TYPE, widgetType);
}
// 将widgetType赋值给mWidgetType
mWidgetType = widgetType;
// 获取note中的originParent
long originParent = note.has(NoteColumns.ORIGIN_PARENT_ID) ? note
.getLong(NoteColumns.ORIGIN_PARENT_ID) : 0;
// 如果mIsCreate为true或者mOriginParent不等于originParent则将originParent添加到mDiffNoteValues中
if (mIsCreate || mOriginParent != originParent) {
mDiffNoteValues.put(NoteColumns.ORIGIN_PARENT_ID, originParent);
}
// 将originParent赋值给mOriginParent
mOriginParent = originParent;
// 遍历dataArray中的每一个JSONObject
for (int i = 0; i < dataArray.length(); i++) {
JSONObject data = dataArray.getJSONObject(i);
SqlData sqlData = null;
// 判断data中是否有ID字段
if (data.has(DataColumns.ID)) {
// 获取ID字段的值
long dataId = data.getLong(DataColumns.ID);
// 遍历mDataList中的每一个SqlData
for (SqlData temp : mDataList) {
// 如果ID字段的值和SqlData的ID值相等
if (dataId == temp.getId()) {
// 将temp赋值给sqlData
sqlData = temp;
}
}
}
// 如果sqlData为null则创建一个新的SqlData
if (sqlData == null) {
sqlData = new SqlData(mContext);
// 将sqlData添加到mDataList中
mDataList.add(sqlData);
}
// 设置SqlData的内容
sqlData.setContent(data);
}
}
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
return false;
}
return true;
}
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
JSONObject note = new JSONObject();
// 如果mType等于Notes.TYPE_NOTE
if (mType == Notes.TYPE_NOTE) {
// 将mId放入note中
note.put(NoteColumns.ID, mId);
// 将mAlertDate放入note中
note.put(NoteColumns.ALERTED_DATE, mAlertDate);
// 将mBgColorId放入note中
note.put(NoteColumns.BG_COLOR_ID, mBgColorId);
// 将mCreatedDate放入note中
note.put(NoteColumns.CREATED_DATE, mCreatedDate);
// 将mHasAttachment放入note中
note.put(NoteColumns.HAS_ATTACHMENT, mHasAttachment);
// 将mModifiedDate放入note中
note.put(NoteColumns.MODIFIED_DATE, mModifiedDate);
// 将mParentId放入note中
note.put(NoteColumns.PARENT_ID, mParentId);
// 将mSnippet放入note中
note.put(NoteColumns.SNIPPET, mSnippet);
// 将mType放入note中
note.put(NoteColumns.TYPE, mType);
// 将mWidgetId放入note中
note.put(NoteColumns.WIDGET_ID, mWidgetId);
// 将mWidgetType放入note中
note.put(NoteColumns.WIDGET_TYPE, mWidgetType);
// 将mOriginParent放入note中
note.put(NoteColumns.ORIGIN_PARENT_ID, mOriginParent);
// 将note放入js中
js.put(GTaskStringUtils.META_HEAD_NOTE, note);
// 创建一个JSONArray对象dataArray
JSONArray dataArray = new JSONArray();
// 遍历mDataList
for (SqlData sqlData : mDataList) {
// 获取sqlData的content
JSONObject data = sqlData.getContent();
// 如果data不为空
if (data != null) {
// 将data放入dataArray中
dataArray.put(data);
}
}
// 将dataArray放入js中
js.put(GTaskStringUtils.META_HEAD_DATA, dataArray);
// 如果mType等于Notes.TYPE_FOLDER或者mType等于Notes.TYPE_SYSTEM
} else if (mType == Notes.TYPE_FOLDER || mType == Notes.TYPE_SYSTEM) {
// 将mId放入note中
note.put(NoteColumns.ID, mId);
// 将mType放入note中
note.put(NoteColumns.TYPE, mType);
// 将mSnippet放入note中
note.put(NoteColumns.SNIPPET, mSnippet);
// 将note放入js中
js.put(GTaskStringUtils.META_HEAD_NOTE, note);
}
return js;
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
}
return null;
}
// 设置父id
public void setParentId(long id) {
mParentId = id;
mDiffNoteValues.put(NoteColumns.PARENT_ID, id);
}
// 设置GtaskId
public void setGtaskId(String gid) {
mDiffNoteValues.put(NoteColumns.GTASK_ID, gid);
}
// 设置同步id
public void setSyncId(long syncId) {
mDiffNoteValues.put(NoteColumns.SYNC_ID, syncId);
}
// 重置本地修改时间
public void resetLocalModified() {
mDiffNoteValues.put(NoteColumns.LOCAL_MODIFIED, 0);
}
// 获取id
public long getId() {
return mId;
}
//获取父ID
public long getParentId() {
return mParentId;
}
//获取摘要
public String getSnippet() {
return mSnippet;
}
//判断是否为笔记类型
public boolean isNoteType() {
return mType == Notes.TYPE_NOTE;
}
//提交
public void commit(boolean validateVersion) {
if (mIsCreate) {
if (mId == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) {
mDiffNoteValues.remove(NoteColumns.ID);
}
Uri uri = mContentResolver.insert(Notes.CONTENT_NOTE_URI, mDiffNoteValues);
try {
mId = Long.valueOf(uri.getPathSegments().get(1));
} 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");
}
if (mType == Notes.TYPE_NOTE) {
for (SqlData sqlData : mDataList) {
sqlData.commit(mId, false, -1);
}
}
} else {
// 检查mId是否有效
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");
}
// 检查是否有更新
if (mDiffNoteValues.size() > 0) {
// 更新版本号
mVersion ++;
int result = 0;
// 检查是否是同步更新
if (!validateVersion) {
// 更新
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");
}
}
// 判断mType是否为Notes.TYPE_NOTE
if (mType == Notes.TYPE_NOTE) {
// 遍历mDataList
for (SqlData sqlData : mDataList) {
// 提交数据
sqlData.commit(mId, validateVersion, mVersion);
}
}
}
// refresh local info
// 从游标中加载数据
loadFromCursor(mId);
// 判断mType是否为Notes.TYPE_NOTE
if (mType == Notes.TYPE_NOTE)
// 加载数据内容
loadDataContent();
// 清除mDiffNoteValues
mDiffNoteValues.clear();
// 设置mIsCreate为false
mIsCreate = false;
}
}