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/src/model/Note.java

407 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;
/**
* Note类 - 表示应用中的笔记数据模型
*
* 该类是笔记应用的核心数据模型,用于封装笔记的基本信息和内容数据
* 支持文本笔记和通话笔记两种类型,提供了笔记的创建、更新和同步功能
* 采用ContentResolver与ContentProvider进行数据交互实现数据的持久化存储
*
* @author MiCode Open Source Community
*/
public class Note {
/**
* 笔记基本信息的变更值
*/
private ContentValues mNoteDiffValues;
/**
* 笔记内容数据(文本和通话)
*/
private NoteData mNoteData;
/**
* 日志标签
*/
private static final String TAG = "Note";
/**
* 创建一个新的笔记ID并在数据库中插入新笔记
*
* 该方法会在数据库中创建一个新的笔记记录并返回生成的笔记ID
* 新笔记会设置默认的创建时间、修改时间和类型
*
* @param context 上下文对象用于获取ContentResolver
* @param folderId 笔记所属的文件夹ID
* @return 新创建的笔记ID失败返回0
*/
public static synchronized long getNewNoteId(Context context, long folderId) {
try {
// 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);
if (uri == null) {
Log.e(TAG, "Insert note failed, uri is null");
return 0;
}
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;
} catch (IndexOutOfBoundsException e) {
Log.e(TAG, "Get note id error :" + e.toString());
noteId = 0;
}
if (noteId == -1) {
Log.e(TAG, "Wrong note id:" + noteId);
return 0;
}
return noteId;
} catch (Exception e) {
Log.e(TAG, "Create new note error :" + e.toString());
return 0;
}
}
/**
* 默认构造方法
*
* 初始化笔记的基本信息和内容数据对象
*/
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 上下文对象用于获取ContentResolver
* @param noteId 笔记ID
* @return true表示同步成功false表示同步失败
* @throws IllegalArgumentException 如果笔记ID无效
*/
public boolean syncNote(Context context, long noteId) {
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;
}
/**
* NoteData类 - 表示笔记的内容数据(内部类)
*
* 该内部类用于封装笔记的内容数据,包括文本数据和通话数据
* 提供了数据的设置、修改检查和同步到ContentResolver的功能
*/
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
* @throws IllegalArgumentException 如果ID无效
*/
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无效
*/
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 上下文对象用于获取ContentResolver
* @param noteId 所属笔记的ID
* @return 同步成功返回笔记URI失败返回null
* @throws IllegalArgumentException 如果笔记ID无效
*/
Uri pushIntoContentResolver(Context context, long noteId) {
/**
* Check for safety
*/
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;
}
}
}