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.
git.text/src/gtask/data/SqlNote.java

760 lines
27 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;
/**
* <p>本地便签数据操作类用于Google任务同步时的便签元数据与内容数据管理。</p>
* <p>核心职责:</p>
* <ul>
* <li>管理便签的元数据(如标题、类型、修改时间等)</li>
* <li>处理便签的内容数据集合(通过{@link SqlData}</li>
* <li>实现便签数据与JSON格式的相互转换</li>
* <li>提供便签数据的增删改查操作</li>
* <li>支持版本验证以避免并发更新冲突</li>
* </ul>
* <p>设计意图:</p>
* <ul>
* <li>作为Google任务同步与本地数据库之间的桥梁</li>
* <li>封装ContentProvider的复杂操作提供简洁的API</li>
* <li>支持批量提交数据变更,提高性能</li>
* <li>维护数据一致性,确保元数据与内容数据同步更新</li>
* </ul>
* <p>关键关联:</p>
* <ul>
* <li>使用{@link Context}访问系统ContentResolver</li>
* <li>使用{@link ContentProvider}进行本地数据库操作</li>
* <li>与{@link SqlData}协作管理便签内容</li>
* <li>与{@link GTaskManager}集成实现Google任务同步</li>
* </ul>
*/
public class SqlNote {
/**
* <p>日志标签。</p>
* <p>业务含义用于在日志中标识SqlNote类的相关操作便于调试和问题追踪。</p>
*/
private static final String TAG = SqlNote.class.getSimpleName();
/**
* <p>无效ID常量。</p>
* <p>业务含义表示未初始化或无效的便签ID用于边界条件判断。</p>
* <p>取值:-99999</p>
*/
private static final int INVALID_ID = -99999;
/**
* <p>便签查询投影列。</p>
* <p>业务含义定义从ContentProvider查询便签数据时返回的字段集合。</p>
* <p>包含ID、提醒日期、背景颜色ID、创建日期、是否有附件、修改日期等关键字段。</p>
*/
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
};
/**
* <p>ID列索引。</p>
* <p>业务含义PROJECTION_NOTE数组中ID字段的索引位置。</p>
* <p>取值0</p>
*/
public static final int ID_COLUMN = 0;
/**
* <p>提醒日期列索引。</p>
* <p>业务含义PROJECTION_NOTE数组中提醒日期字段的索引位置。</p>
* <p>取值1</p>
*/
public static final int ALERTED_DATE_COLUMN = 1;
/**
* <p>背景颜色ID列索引。</p>
* <p>业务含义PROJECTION_NOTE数组中背景颜色ID字段的索引位置。</p>
* <p>取值2</p>
*/
public static final int BG_COLOR_ID_COLUMN = 2;
/**
* <p>创建日期列索引。</p>
* <p>业务含义PROJECTION_NOTE数组中创建日期字段的索引位置。</p>
* <p>取值3</p>
*/
public static final int CREATED_DATE_COLUMN = 3;
/**
* <p>是否有附件列索引。</p>
* <p>业务含义PROJECTION_NOTE数组中是否有附件字段的索引位置。</p>
* <p>取值4</p>
*/
public static final int HAS_ATTACHMENT_COLUMN = 4;
/**
* <p>修改日期列索引。</p>
* <p>业务含义PROJECTION_NOTE数组中修改日期字段的索引位置。</p>
* <p>取值5</p>
*/
public static final int MODIFIED_DATE_COLUMN = 5;
/**
* <p>便签数量列索引。</p>
* <p>业务含义PROJECTION_NOTE数组中便签数量字段的索引位置。</p>
* <p>取值6</p>
*/
public static final int NOTES_COUNT_COLUMN = 6;
/**
* <p>父ID列索引。</p>
* <p>业务含义PROJECTION_NOTE数组中父ID字段的索引位置。</p>
* <p>取值7</p>
*/
public static final int PARENT_ID_COLUMN = 7;
/**
* <p>摘要列索引。</p>
* <p>业务含义PROJECTION_NOTE数组中摘要字段的索引位置。</p>
* <p>取值8</p>
*/
public static final int SNIPPET_COLUMN = 8;
/**
* <p>类型列索引。</p>
* <p>业务含义PROJECTION_NOTE数组中类型字段的索引位置。</p>
* <p>取值9</p>
*/
public static final int TYPE_COLUMN = 9;
/**
* <p>小组件ID列索引。</p>
* <p>业务含义PROJECTION_NOTE数组中小组件ID字段的索引位置。</p>
* <p>取值10</p>
*/
public static final int WIDGET_ID_COLUMN = 10;
/**
* <p>小组件类型列索引。</p>
* <p>业务含义PROJECTION_NOTE数组中小组件类型字段的索引位置。</p>
* <p>取值11</p>
*/
public static final int WIDGET_TYPE_COLUMN = 11;
/**
* <p>同步ID列索引。</p>
* <p>业务含义PROJECTION_NOTE数组中同步ID字段的索引位置。</p>
* <p>取值12</p>
*/
public static final int SYNC_ID_COLUMN = 12;
/**
* <p>本地修改列索引。</p>
* <p>业务含义PROJECTION_NOTE数组中本地修改字段的索引位置。</p>
* <p>取值13</p>
*/
public static final int LOCAL_MODIFIED_COLUMN = 13;
/**
* <p>原始父ID列索引。</p>
* <p>业务含义PROJECTION_NOTE数组中原始父ID字段的索引位置。</p>
* <p>取值14</p>
*/
public static final int ORIGIN_PARENT_ID_COLUMN = 14;
/**
* <p>Google任务ID列索引。</p>
* <p>业务含义PROJECTION_NOTE数组中Google任务ID字段的索引位置。</p>
* <p>取值15</p>
*/
public static final int GTASK_ID_COLUMN = 15;
/**
* <p>版本列索引。</p>
* <p>业务含义PROJECTION_NOTE数组中版本字段的索引位置。</p>
* <p>取值16</p>
*/
public static final int VERSION_COLUMN = 16;
/**
* <p>上下文对象。</p>
* <p>业务含义用于访问系统资源和ContentResolver。</p>
* <p>使用场景在构造函数中初始化用于后续的ContentProvider操作。</p>
*/
private Context mContext;
/**
* <p>内容解析器。</p>
* <p>业务含义用于与ContentProvider进行交互执行数据库操作。</p>
* <p>使用场景在构造函数中初始化用于后续的CRUD操作。</p>
*/
private ContentResolver mContentResolver;
/**
* <p>是否为新创建的便签。</p>
* <p>业务含义:标识当前便签对象是否已在数据库中创建。</p>
* <p>使用场景:在构造函数中初始化,用于确定执行插入或更新操作。</p>
*/
private boolean mIsCreate;
/**
* <p>便签ID。</p>
* <p>业务含义:便签在本地数据库中的唯一标识符。</p>
* <p>默认值INVALID_ID-99999</p>
*/
private long mId;
/**
* <p>提醒日期。</p>
* <p>业务含义:便签的提醒时间戳。</p>
* <p>默认值0表示无提醒</p>
*/
private long mAlertDate;
/**
* <p>背景颜色ID。</p>
* <p>业务含义便签的背景颜色资源ID。</p>
* <p>默认值通过ResourceParser.getDefaultBgId(context)获取</p>
*/
private int mBgColorId;
/**
* <p>创建日期。</p>
* <p>业务含义:便签创建的时间戳。</p>
* <p>默认值:当前系统时间</p>
*/
private long mCreatedDate;
/**
* <p>是否有附件。</p>
* <p>业务含义:标识便签是否包含附件。</p>
* <p>取值0无附件或1有附件</p>
* <p>默认值0</p>
*/
private int mHasAttachment;
/**
* <p>修改日期。</p>
* <p>业务含义:便签最后一次修改的时间戳。</p>
* <p>默认值:当前系统时间</p>
*/
private long mModifiedDate;
/**
* <p>父便签ID。</p>
* <p>业务含义便签所属的父文件夹ID。</p>
* <p>默认值0表示根目录</p>
*/
private long mParentId;
/**
* <p>便签摘要。</p>
* <p>业务含义:便签的标题或简短描述。</p>
* <p>默认值:空字符串</p>
*/
private String mSnippet;
/**
* <p>便签类型。</p>
* <p>业务含义:便签的类型(如普通便签、文件夹等)。</p>
* <p>默认值Notes.TYPE_NOTE</p>
*/
private int mType;
/**
* <p>小组件ID。</p>
* <p>业务含义关联的桌面小组件ID。</p>
* <p>默认值AppWidgetManager.INVALID_APPWIDGET_ID</p>
*/
private int mWidgetId;
/**
* <p>小组件类型。</p>
* <p>业务含义:关联的桌面小组件类型。</p>
* <p>默认值Notes.TYPE_WIDGET_INVALIDE</p>
*/
private int mWidgetType;
/**
* <p>原始父便签ID。</p>
* <p>业务含义便签原始所属的父文件夹ID用于同步操作。</p>
* <p>默认值0</p>
*/
private long mOriginParent;
/**
* <p>版本号。</p>
* <p>业务含义:便签的版本号,用于并发更新冲突检测。</p>
* <p>默认值0</p>
*/
private long mVersion;
/**
* <p>便签元数据变更集合。</p>
* <p>业务含义:存储便签元数据的变更内容,用于批量更新。</p>
* <p>使用场景在setContent方法中记录变更在commit方法中提交变更。</p>
*/
private ContentValues mDiffNoteValues;
/**
* <p>便签内容数据集合。</p>
* <p>业务含义:存储便签的内容数据列表。</p>
* <p>使用场景与SqlData类协作管理便签的具体内容。</p>
*/
private ArrayList<SqlData> mDataList;
/**
* <p>创建一个新的SqlNote实例。</p>
* <p>功能:初始化一个新的便签对象,设置默认值。</p>
* <p>业务逻辑:</p>
* <ul>
* <li>设置mIsCreate为true表示这是一个新创建的便签</li>
* <li>初始化所有字段为默认值</li>
* <li>创建空的变更集合和数据列表</li>
* </ul>
*
* @param context 上下文对象用于访问系统资源和ContentResolver
*/
public SqlNote(Context context) {
mContext = context;
mContentResolver = context.getContentResolver();
mIsCreate = true;
mId = INVALID_ID;
mAlertDate = 0;
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>();
}
/**
* <p>从Cursor创建SqlNote实例。</p>
* <p>功能:从数据库查询结果创建便签对象。</p>
* <p>业务逻辑:</p>
* <ul>
* <li>设置mIsCreate为false表示这是一个已存在的便签</li>
* <li>从Cursor加载便签数据</li>
* <li>如果是普通便签,加载便签内容</li>
* <li>创建空的变更集合</li>
* </ul>
*
* @param context 上下文对象用于访问系统资源和ContentResolver
* @param c 查询结果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();
}
/**
* <p>通过ID创建SqlNote实例。</p>
* <p>功能根据便签ID从数据库加载便签对象。</p>
* <p>业务逻辑:</p>
* <ul>
* <li>设置mIsCreate为false表示这是一个已存在的便签</li>
* <li>根据ID查询数据库并加载便签数据</li>
* <li>如果是普通便签,加载便签内容</li>
* <li>创建空的变更集合</li>
* </ul>
*
* @param context 上下文对象用于访问系统资源和ContentResolver
* @param id 便签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 {
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 {
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 {
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) {
// for folder we can only update the snnipet and type
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;
}
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) {
note.put(NoteColumns.ID, mId);
note.put(NoteColumns.ALERTED_DATE, mAlertDate);
note.put(NoteColumns.BG_COLOR_ID, mBgColorId);
note.put(NoteColumns.CREATED_DATE, mCreatedDate);
note.put(NoteColumns.HAS_ATTACHMENT, mHasAttachment);
note.put(NoteColumns.MODIFIED_DATE, mModifiedDate);
note.put(NoteColumns.PARENT_ID, mParentId);
note.put(NoteColumns.SNIPPET, mSnippet);
note.put(NoteColumns.TYPE, mType);
note.put(NoteColumns.WIDGET_ID, mWidgetId);
note.put(NoteColumns.WIDGET_TYPE, mWidgetType);
note.put(NoteColumns.ORIGIN_PARENT_ID, mOriginParent);
js.put(GTaskStringUtils.META_HEAD_NOTE, note);
JSONArray dataArray = new JSONArray();
for (SqlData sqlData : mDataList) {
JSONObject data = sqlData.getContent();
if (data != null) {
dataArray.put(data);
}
}
js.put(GTaskStringUtils.META_HEAD_DATA, dataArray);
} else if (mType == Notes.TYPE_FOLDER || mType == Notes.TYPE_SYSTEM) {
note.put(NoteColumns.ID, mId);
note.put(NoteColumns.TYPE, mType);
note.put(NoteColumns.SNIPPET, mSnippet);
js.put(GTaskStringUtils.META_HEAD_NOTE, note);
}
return js;
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
}
return null;
}
public void setParentId(long id) {
mParentId = id;
mDiffNoteValues.put(NoteColumns.PARENT_ID, id);
}
public void setGtaskId(String gid) {
mDiffNoteValues.put(NoteColumns.GTASK_ID, gid);
}
public void setSyncId(long syncId) {
mDiffNoteValues.put(NoteColumns.SYNC_ID, syncId);
}
public void resetLocalModified() {
mDiffNoteValues.put(NoteColumns.LOCAL_MODIFIED, 0);
}
public long getId() {
return mId;
}
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 {
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");
}
}
if (mType == Notes.TYPE_NOTE) {
for (SqlData sqlData : mDataList) {
sqlData.commit(mId, validateVersion, mVersion);
}
}
}
// refresh local info
loadFromCursor(mId);
if (mType == Notes.TYPE_NOTE)
loadDataContent();
mDiffNoteValues.clear();
mIsCreate = false;
}
}