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.
xiaomi_notes_reading/src/notes/gtask/data/SqlData.java

227 lines
8.7 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.content.ContentResolver;
import android.content.ContentUris;
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.DataConstants;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.NotesDatabaseHelper.TABLE;
import net.micode.notes.gtask.exception.ActionFailureException;
import org.json.JSONException;
import org.json.JSONObject;
/**
*管理便签应用中的数据项(如文本、图片等),
* 负责数据项的加载、从JSON解析数据、生成JSON数据、数据库交互插入 / 更新)及版本冲突控制,
* 是便签数据在内存与数据库之间的中间层处理类。
*/
public class SqlData {
private static final String TAG = SqlData.class.getSimpleName();
private static final int INVALID_ID = -99999;
public static final String[] PROJECTION_DATA = new String[] {
DataColumns.ID, DataColumns.MIME_TYPE, DataColumns.CONTENT, DataColumns.DATA1,
DataColumns.DATA3
};
public static final int DATA_ID_COLUMN = 0;
//区分数据项,比如文本、图片、附件等,由此决定数据解析方式
public static final int DATA_MIME_TYPE_COLUMN = 1;
//存储数据项的核心内容
public static final int DATA_CONTENT_COLUMN = 2;
//存储content辅助信息比如图片的宽度大小等
public static final int DATA_CONTENT_DATA_1_COLUMN = 3;
//更多扩展信息
public static final int DATA_CONTENT_DATA_3_COLUMN = 4;
private ContentResolver mContentResolver;
//false表示新创建的未入库数据项true表示数据库中已经创建的数据项
private boolean mIsCreate;
private long mDataId;
private String mDataMimeType;
private String mDataContent;
private long mDataContentData1;
private String mDataContentData3;
private ContentValues mDiffDataValues;
/**
* mContentResolver是什么
* @param context
*/
public SqlData(Context context) {
mContentResolver = context.getContentResolver();
mIsCreate = true;
mDataId = INVALID_ID;
mDataMimeType = DataConstants.NOTE;
mDataContent = "";
mDataContentData1 = 0;
mDataContentData3 = "";
mDiffDataValues = new ContentValues();
}
public SqlData(Context context, Cursor c) {
mContentResolver = context.getContentResolver();
mIsCreate = false;
loadFromCursor(c);
mDiffDataValues = new ContentValues();
}
private void loadFromCursor(Cursor c) {
mDataId = c.getLong(DATA_ID_COLUMN);
mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN);
mDataContent = c.getString(DATA_CONTENT_COLUMN);
mDataContentData1 = c.getLong(DATA_CONTENT_DATA_1_COLUMN);
mDataContentData3 = c.getString(DATA_CONTENT_DATA_3_COLUMN);
}
/**
* 将JSON中的数据项属性映射到SqlData实例的成员变量
* 记录变更的字段到mDifferentValues中为后续数据库增量更新做准备
* 数据序列化JSON js->实例
* @param js
* @throws JSONException
*/
public void setContent(JSONObject js) throws JSONException {
long dataId = js.has(DataColumns.ID) ? js.getLong(DataColumns.ID) : INVALID_ID;
//新创建的未入库数据项或者是当前实例的已有ID和JSON中解析的ID不一样说明该字段发生了变更
if (mIsCreate || mDataId != dataId) {
mDiffDataValues.put(DataColumns.ID, dataId);
}
mDataId = dataId;
//判断JSON中是否包含MIME_TYPE键否则默认为纯文本
String dataMimeType = js.has(DataColumns.MIME_TYPE) ? js.getString(DataColumns.MIME_TYPE)
: DataConstants.NOTE;
if (mIsCreate || !mDataMimeType.equals(dataMimeType)) {
mDiffDataValues.put(DataColumns.MIME_TYPE, dataMimeType);
}
mDataMimeType = dataMimeType;
//判断JSON中是否包含CONTENT键如便签文本等否则赋值为空串
String dataContent = js.has(DataColumns.CONTENT) ? js.getString(DataColumns.CONTENT) : "";
if (mIsCreate || !mDataContent.equals(dataContent)) {
mDiffDataValues.put(DataColumns.CONTENT, dataContent);
}
mDataContent = dataContent;
//判断DATA1键如图片宽度等
long dataContentData1 = js.has(DataColumns.DATA1) ? js.getLong(DataColumns.DATA1) : 0;
if (mIsCreate || mDataContentData1 != dataContentData1) {
mDiffDataValues.put(DataColumns.DATA1, dataContentData1);
}
mDataContentData1 = dataContentData1;
//判断DATA3键
String dataContentData3 = js.has(DataColumns.DATA3) ? js.getString(DataColumns.DATA3) : "";
if (mIsCreate || !mDataContentData3.equals(dataContentData3)) {
mDiffDataValues.put(DataColumns.DATA3, dataContentData3);
}
mDataContentData3 = dataContentData3;
}
public JSONObject getContent() throws JSONException {
if (mIsCreate) {
Log.e(TAG, "it seems that we haven't created this in database yet");
return null;
}
JSONObject js = new JSONObject();
js.put(DataColumns.ID, mDataId);
js.put(DataColumns.MIME_TYPE, mDataMimeType);
js.put(DataColumns.CONTENT, mDataContent);
js.put(DataColumns.DATA1, mDataContentData1);
js.put(DataColumns.DATA3, mDataContentData3);
return js;
}
/**
* 将数据项提交到数据库,根据数据项是否为新建,分别执行插入或者更新操作,同时支持版本验证,
* 最终清理变更记录,更新实例状态
* @param noteId 数据项关联的便签ID
* @param validateVersion 版本验证布尔值,防止多人或者多设备同时改,避免改乱
* @param version 要验证的版本号
*/
public void commit(long noteId, boolean validateVersion, long version) {
//新创建的项,“插入”
if (mIsCreate) {
//未入库数据库未生成主键所以当前数据项ID为无效值
if (mDataId == INVALID_ID && mDiffDataValues.containsKey(DataColumns.ID)) {
mDiffDataValues.remove(DataColumns.ID);
}
mDiffDataValues.put(DataColumns.NOTE_ID, noteId);
Uri uri = mContentResolver.insert(Notes.CONTENT_DATA_URI, mDiffDataValues);
try { //从数据库返回的地址里抠出数据项的ID
mDataId = Long.valueOf(uri.getPathSegments().get(1));
} catch (NumberFormatException e) {
Log.e(TAG, "Get note id error :" + e.toString());
throw new ActionFailureException("create note failed");
}
} else { //数据库里本来就有这个项,只是更改内容
if (mDiffDataValues.size() > 0) {
int result = 0;
//不需要防止多设备更改冲突
if (!validateVersion) {
result = mContentResolver.update(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, null, null);
} else { //需要防止多设备更改冲突
result = mContentResolver.update(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues,
" ? in (SELECT " + NoteColumns.ID + " FROM " + TABLE.NOTE
+ " WHERE " + NoteColumns.VERSION + "=?)", new String[] {
String.valueOf(noteId), String.valueOf(version)
});
}
if (result == 0) {
Log.w(TAG, "there is no update. maybe user updates note when syncing");
}
}
}
mDiffDataValues.clear();
mIsCreate = false;
}
public long getId() {
return mDataId;
}
}