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.

393 lines
13 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.
*/
/**
* 文件: Note.java
* 描述: 便签数据模型类,用于管理便签的创建、更新和同步
* 作用: 提供便签数据的CRUD操作接口是应用模型层的核心类之一
*/
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
*/
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);
// 插入便签记录并获取URI
Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values);
// 从URI中提取便签ID
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;
}
// 验证便签ID有效性
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 同步成功返回true失败返回false
*/
public boolean syncNote(Context context, long noteId) {
// 验证便签ID有效性
if (noteId <= 0) {
throw new IllegalArgumentException("Wrong note id:" + noteId);
}
// 如果没有本地修改,直接返回成功
if (!isLocalModified()) {
return true;
}
/**
* In theory, once data changed, the note should be updated on {@link NoteColumns#LOCAL_MODIFIED} and
* {@link NoteColumns#MODIFIED_DATE}. For data safety, though update note fails, we also update the
* note data info
*/
// 更新便签基本信息
if (context.getContentResolver().update(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null,
null) == 0) {
Log.e(TAG, "Update note error, should not happen");
// Do not return, fall through
}
mNoteDiffValues.clear();
// 更新便签内容数据
if (mNoteData.isLocalModified()
&& (mNoteData.pushIntoContentResolver(context, noteId) == null)) {
return 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;
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("Text data id should larger than 0");
}
mTextDataId = id;
}
/**
* 设置通话记录数据ID
*
* @param id 通话记录数据ID
*/
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 成功返回便签URI失败返回null
*/
Uri pushIntoContentResolver(Context context, long noteId) {
/**
* Check for safety
*/
// 验证便签ID有效性
if (noteId <= 0) {
throw new IllegalArgumentException("Wrong note 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 {
setTextDataId(Long.valueOf(uri.getPathSegments().get(1)));
} catch (NumberFormatException e) {
Log.e(TAG, "Insert new text data fail with noteId" + 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 {
setCallDataId(Long.valueOf(uri.getPathSegments().get(1)));
} catch (NumberFormatException e) {
Log.e(TAG, "Insert new call data fail with noteId" + 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;
}
}
}