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.

360 lines
12 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.
*/
/*
* 版权所有 (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* 根据 Apache License 2.0 授权
*/
package net.micode.notes.model;
// 导入必要的Android类和包
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
*/
public static synchronized long getNewNoteId(Context context, long folderId) {
// 创建新笔记的内容值对象
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); // 父文件夹ID
// 将新笔记插入数据库
Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values);
long noteId = 0;
try {
// 从返回的URI中解析出笔记ID
noteId = Long.valueOf(uri.getPathSegments().get(1));
} catch (NumberFormatException e) {
Log.e(TAG, "获取笔记ID错误:" + e.toString());
noteId = 0;
}
if (noteId == -1) {
throw new IllegalStateException("错误的笔记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 同步是否成功
*/
public boolean syncNote(Context context, long noteId) {
if (noteId <= 0) {
throw new IllegalArgumentException("错误的笔记ID:" + noteId);
}
// 如果没有修改,直接返回成功
if (!isLocalModified()) {
return true;
}
/**
* 理论上数据变更后笔记应该在LOCAL_MODIFIED和MODIFIED_DATE字段更新
* 为了数据安全,即使笔记更新失败,我们也会更新笔记数据信息
*/
if (context.getContentResolver().update(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null,
null) == 0) {
Log.e(TAG, "更新笔记错误,不应该发生");
// 不返回,继续执行
}
mNoteDiffValues.clear();
// 如果有数据修改且推送失败,返回失败
if (mNoteData.isLocalModified()
&& (mNoteData.pushIntoContentResolver(context, noteId) == null)) {
return false;
}
return true;
}
/**
* 内部类,处理笔记的具体数据内容
*/
private class NoteData {
private long mTextDataId; // 文本数据ID
private ContentValues mTextDataValues; // 文本数据值
private long mCallDataId; // 通话数据ID
private ContentValues mCallDataValues; // 通话数据值
private static final String TAG = "NoteData";
/**
* 构造函数,初始化数据
*/
public NoteData() {
mTextDataValues = new ContentValues();
mCallDataValues = new ContentValues();
mTextDataId = 0;
mCallDataId = 0;
}
/**
* 检查数据是否有本地修改
* @return 如果有修改返回true否则返回false
*/
boolean isLocalModified() {
return mTextDataValues.size() > 0 || mCallDataValues.size() > 0;
}
/**
* 设置文本数据ID
* @param id 文本数据ID
*/
void setTextDataId(long id) {
if(id <= 0) {
throw new IllegalArgumentException("文本数据ID应大于0");
}
mTextDataId = id;
}
/**
* 设置通话数据ID
* @param id 通话数据ID
*/
void setCallDataId(long id) {
if (id <= 0) {
throw new IllegalArgumentException("通话数据ID应大于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());
}
/**
* 将数据推送到内容提供者
* @param context 应用上下文
* @param noteId 笔记ID
* @return 操作结果的URI失败返回null
*/
Uri pushIntoContentResolver(Context context, long noteId) {
// 安全检查
if (noteId <= 0) {
throw new IllegalArgumentException("错误的笔记ID:" + noteId);
}
// 创建操作列表
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
ContentProviderOperation.Builder builder = null;
// 处理文本数据
if(mTextDataValues.size() > 0) {
mTextDataValues.put(DataColumns.NOTE_ID, noteId);
if (mTextDataId == 0) {
// 如果是新文本数据,插入新记录
mTextDataValues.put(DataColumns.MIME_TYPE, TextNote.CONTENT_ITEM_TYPE);
Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI,
mTextDataValues);
try {
// 设置新插入的文本数据ID
setTextDataId(Long.valueOf(uri.getPathSegments().get(1)));
} catch (NumberFormatException e) {
Log.e(TAG, "插入新文本数据失败笔记ID:" + noteId);
mTextDataValues.clear();
return 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);
if (mCallDataId == 0) {
// 如果是新通话数据,插入新记录
mCallDataValues.put(DataColumns.MIME_TYPE, CallNote.CONTENT_ITEM_TYPE);
Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI,
mCallDataValues);
try {
// 设置新插入的通话数据ID
setCallDataId(Long.valueOf(uri.getPathSegments().get(1)));
} catch (NumberFormatException e) {
Log.e(TAG, "插入新通话数据失败笔记ID:" + noteId);
mCallDataValues.clear();
return 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);
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;
} catch (OperationApplicationException e) {
Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
return null;
}
}
return null;
}
}
}