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-test/src/net/micode/notes/model/Note.java

380 lines
14 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.model;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.net.Uri;
import android.os.RemoteException;
import android.util.Log;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.CallNote;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.Notes.TextNote;
import java.util.ArrayList;
/**
* 小米便签的业务逻辑模型类
* 用于管理便签的数据和操作,包括创建、修改、同步等
* 支持普通文本便签和通话记录便签
*/
public class Note {
/**
* 便签差异值,用于存储便签的修改内容
* 当便签属性发生变化时,将变化的属性存入此对象
*/
private ContentValues mNoteDiffValues;
/**
* 便签数据对象,用于存储便签的具体内容
*/
private NoteData mNoteData;
/**
* 日志标签,用于在日志系统中标识本类的日志信息
*/
private static final String TAG = "Note";
/**
* 为添加新便签到数据库创建一个新的便签ID
* @param context 上下文对象
* @param folderId 文件夹ID新便签将存储在此文件夹中
* @return 新创建的便签ID
* @throws IllegalStateException 当创建便签失败时抛出
*/
public static synchronized long getNewNoteId(Context context, long folderId) {
// Create a new note in the database
ContentValues values = new ContentValues();
long createdTime = System.currentTimeMillis();
values.put(NoteColumns.CREATED_DATE, createdTime);
values.put(NoteColumns.MODIFIED_DATE, createdTime);
values.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
values.put(NoteColumns.LOCAL_MODIFIED, 1);
values.put(NoteColumns.PARENT_ID, folderId);
Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values);
long noteId = 0;
try {
noteId = Long.valueOf(uri.getPathSegments().get(1));
} catch (NumberFormatException e) {
Log.e(TAG, "Get note id error :" + e.toString());
noteId = 0;
}
if (noteId == -1) {
throw new IllegalStateException("Wrong note id:" + noteId);
}
return noteId;
}
/**
* 构造方法,初始化便签对象
*/
public Note() {
mNoteDiffValues = new ContentValues(); // 初始化便签差异值
mNoteData = new NoteData(); // 初始化便签数据
}
/**
* 设置便签的属性值
* @param key 属性名
* @param value 属性值
*/
public void setNoteValue(String key, String value) {
mNoteDiffValues.put(key, value); // 存储属性变化
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); // 标记为本地修改
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); // 更新修改时间
}
/**
* 设置文本便签的数据
* @param key 数据键
* @param value 数据值
*/
public void setTextData(String key, String value) {
mNoteData.setTextData(key, value);
}
/**
* 设置文本便签的数据ID
* @param id 文本便签数据ID
*/
public void setTextDataId(long id) {
mNoteData.setTextDataId(id);
}
/**
* 获取文本便签的数据ID
* @return 文本便签数据ID
*/
public long getTextDataId() {
return mNoteData.mTextDataId;
}
/**
* 设置通话记录便签的数据ID
* @param id 通话记录便签数据ID
*/
public void setCallDataId(long id) {
mNoteData.setCallDataId(id);
}
/**
* 设置通话记录便签的数据
* @param key 数据键
* @param value 数据值
*/
public void setCallData(String key, String value) {
mNoteData.setCallData(key, value);
}
/**
* 检查便签是否在本地被修改
* @return 如果便签在本地被修改则返回true否则返回false
*/
public boolean isLocalModified() {
return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified();
}
/**
* 将便签的修改同步到数据库
* @param context 上下文对象
* @param noteId 便签ID
* @return 同步是否成功
* @throws IllegalArgumentException 当便签ID无效时抛出
*/
public boolean syncNote(Context context, long noteId) {
if (noteId <= 0) {
throw new IllegalArgumentException("Wrong note id:" + noteId);
}
// 如果便签没有被修改,直接返回成功
if (!isLocalModified()) {
return true;
}
/**
* 理论上,一旦数据改变,便签应该更新 {@link NoteColumns#LOCAL_MODIFIED} 和
* {@link NoteColumns#MODIFIED_DATE}。为了数据安全,即使更新便签失败,我们也会更新
* 便签数据信息
*/
// 更新便签属性
if (context.getContentResolver().update(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null,
null) == 0) {
Log.e(TAG, "Update note error, should not happen");
// 不返回,继续执行后续操作
}
mNoteDiffValues.clear(); // 清空便签差异值
// 如果便签数据被修改,将数据同步到数据库
if (mNoteData.isLocalModified()
&& (mNoteData.pushIntoContentResolver(context, noteId) == null)) {
return false; // 数据同步失败返回false
}
return true; // 同步成功
}
/**
* 便签数据内部类,用于管理便签的具体内容
* 支持普通文本便签和通话记录便签
*/
private class NoteData {
/**
* 文本便签的数据ID
*/
private long mTextDataId;
/**
* 文本便签的差异值,用于存储文本便签的修改内容
*/
private ContentValues mTextDataValues;
/**
* 通话记录便签的数据ID
*/
private long mCallDataId;
/**
* 通话记录便签的差异值,用于存储通话记录便签的修改内容
*/
private ContentValues mCallDataValues;
/**
* 日志标签,用于在日志系统中标识本类的日志信息
*/
private static final String TAG = "NoteData";
/**
* 构造方法,初始化便签数据对象
*/
public NoteData() {
mTextDataValues = new ContentValues(); // 初始化文本便签差异值
mCallDataValues = new ContentValues(); // 初始化通话记录便签差异值
mTextDataId = 0; // 初始化文本便签数据ID
mCallDataId = 0; // 初始化通话记录便签数据ID
}
/**
* 检查便签数据是否在本地被修改
* @return 如果便签数据在本地被修改则返回true否则返回false
*/
boolean isLocalModified() {
return mTextDataValues.size() > 0 || mCallDataValues.size() > 0;
}
/**
* 设置文本便签的数据ID
* @param id 文本便签数据ID
* @throws IllegalArgumentException 当ID小于等于0时抛出
*/
void setTextDataId(long id) {
if(id <= 0) {
throw new IllegalArgumentException("Text data id should larger than 0");
}
mTextDataId = id;
}
/**
* 设置通话记录便签的数据ID
* @param id 通话记录便签数据ID
* @throws IllegalArgumentException 当ID小于等于0时抛出
*/
void setCallDataId(long id) {
if (id <= 0) {
throw new IllegalArgumentException("Call data id should larger than 0");
}
mCallDataId = id;
}
/**
* 设置通话记录便签的数据
* @param key 数据键
* @param value 数据值
*/
void setCallData(String key, String value) {
mCallDataValues.put(key, value); // 存储通话记录数据变化
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); // 标记为本地修改
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); // 更新修改时间
}
/**
* 设置文本便签的数据
* @param key 数据键
* @param value 数据值
*/
void setTextData(String key, String value) {
mTextDataValues.put(key, value); // 存储文本数据变化
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); // 标记为本地修改
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); // 更新修改时间
}
/**
* 将便签数据推送到ContentResolver
* @param context 上下文对象
* @param noteId 便签ID
* @return 操作成功返回null失败返回null
* @throws IllegalArgumentException 当便签ID无效时抛出
*/
Uri pushIntoContentResolver(Context context, long noteId) {
/**
* 安全性检查
*/
if (noteId <= 0) {
throw new IllegalArgumentException("Wrong note id:" + noteId);
}
// 创建ContentProvider操作列表用于批量处理数据操作
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
ContentProviderOperation.Builder builder = null;
// 处理文本便签数据
if(mTextDataValues.size() > 0) {
mTextDataValues.put(DataColumns.NOTE_ID, noteId); // 设置便签ID
if (mTextDataId == 0) {
// 插入新的文本便签数据
mTextDataValues.put(DataColumns.MIME_TYPE, TextNote.CONTENT_ITEM_TYPE); // 设置MIME类型
Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, mTextDataValues);
try {
setTextDataId(Long.valueOf(uri.getPathSegments().get(1))); // 获取新插入的数据ID
} catch (NumberFormatException e) {
Log.e(TAG, "Insert new text data fail with noteId" + noteId);
mTextDataValues.clear();
return null; // 插入失败返回null
}
} else {
// 更新现有文本便签数据
builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mTextDataId));
builder.withValues(mTextDataValues);
operationList.add(builder.build());
}
mTextDataValues.clear(); // 清空文本便签差异值
}
// 处理通话记录便签数据
if(mCallDataValues.size() > 0) {
mCallDataValues.put(DataColumns.NOTE_ID, noteId); // 设置便签ID
if (mCallDataId == 0) {
// 插入新的通话记录便签数据
mCallDataValues.put(DataColumns.MIME_TYPE, CallNote.CONTENT_ITEM_TYPE); // 设置MIME类型
Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, mCallDataValues);
try {
setCallDataId(Long.valueOf(uri.getPathSegments().get(1))); // 获取新插入的数据ID
} catch (NumberFormatException e) {
Log.e(TAG, "Insert new call data fail with noteId" + noteId);
mCallDataValues.clear();
return null; // 插入失败返回null
}
} else {
// 更新现有通话记录便签数据
builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mCallDataId));
builder.withValues(mCallDataValues);
operationList.add(builder.build());
}
mCallDataValues.clear(); // 清空通话记录便签差异值
}
// 如果有操作需要执行,应用批量操作
if (operationList.size() > 0) {
try {
ContentProviderResult[] results = context.getContentResolver().applyBatch(
Notes.AUTHORITY, operationList);
// 返回操作结果成功返回便签URI失败返回null
return (results == null || results.length == 0 || results[0] == null) ? null
: ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId);
} catch (RemoteException e) {
Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
return null; // 远程异常返回null
} catch (OperationApplicationException e) {
Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
return null; // 操作应用异常返回null
}
}
return null; // 没有操作需要执行返回null
}
}
}