/* * 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 �����ڹ����ʼǵĴ��������º�ͬ���� * �����ṩ�˴����±ʼǡ����ñʼ����ݡ�ͬ���ʼǵȹ��ܡ� */ public class Note { private ContentValues mNoteDiffValues; private NoteData mNoteData; private static final String TAG = "Note"; /** * Create a new note id for adding a new note to databases */ /* * ����һ���µıʼ� ID�����ڽ��±ʼ����ӵ����ݿ��С� * * @param context Ӧ�ó��������� * @param folderId �ļ��� ID * @return �´����ıʼ� ID */ public static synchronized long getNewNoteId(Context context, long folderId) { // Create a new note in the database // ����һ���µıʼǵ����ݿ��� ContentValues values = new ContentValues(); //����һ���µ� ContentValues �������ڴ洢�ʼǵij�ʼֵ�� long createdTime = System.currentTimeMillis(); //��ȡ��ǰʱ�������Ϊ�ʼǵĴ���ʱ�����ʱ�䡣 values.put(NoteColumns.CREATED_DATE, createdTime); //������ʱ��洢�� ContentValues �����С� values.put(NoteColumns.MODIFIED_DATE, createdTime); //����ʱ��洢�� ContentValues �����С� values.put(NoteColumns.TYPE, Notes.TYPE_NOTE); //���ʼ����ʹ洢�� ContentValues �����С� values.put(NoteColumns.LOCAL_MODIFIED, 1); //�������ı�־����Ϊ 1����ʾ�ʼ��ѱ��ġ� values.put(NoteColumns.PARENT_ID, folderId); //���ļ��� ID �洢�� ContentValues �����С� Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values); //�� ContentValues ������뵽���ݿ��У��������´����ʼǵ� URI�� long noteId = 0;//��ʼ���ʼ� ID ������ try { //���Դ� URI �л�ȡ�ʼ� ID��������� NumberFormatException �쳣�����¼������־�������ʼ� ID ����Ϊ 0�� noteId = Long.valueOf(uri.getPathSegments().get(1)); } catch (NumberFormatException e) { Log.e(TAG, "Get note id error :" + e.toString()); noteId = 0; } if (noteId == -1) { //���ʼ� ID �Ƿ�Ϊ -1�����Ϊ -1�����׳� IllegalStateException �쳣�� throw new IllegalStateException("Wrong note id:" + noteId); } return noteId;//�����´����ıʼ� ID�� } /* * ���캯������ʼ���ʼǵIJ���ֵ�ͱʼ����ݡ� */ public Note() { //// ��ʼ���ʼǵIJ���ֵ mNoteDiffValues = new ContentValues(); // // ��ʼ���ʼ����� mNoteData = new NoteData(); } /* * ���ñʼǵIJ���ֵ�� * @param key �� * @param value ֵ */ public void setNoteValue(String key, String value) { // ����ֵ�Դ洢���ʼǵIJ���ֵ�� mNoteDiffValues.put(key, value); // ���ñ����ı�־Ϊ 1����ʾ�ʼ��ѱ��� mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); // ������ʱ��Ϊ��ǰʱ�� mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); } /* * ���ñʼǵ��ı����ݡ� * @param key �� * @param value ֵ */ public void setTextData(String key, String value) { // ���� NoteData ��� setTextData �����������ı����� mNoteData.setTextData(key, value); } /* * ���ñʼǵ��ı����� ID�� * @param id �ı����� ID */ public void setTextDataId(long id) { // ���� NoteData ��� setTextDataId �����������ı����� ID mNoteData.setTextDataId(id); } /* * ��ȡ�ʼǵ��ı����� ID�� * @return �ı����� ID */ public long getTextDataId() { // ���� NoteData ��� mTextDataId �ֶ� return mNoteData.mTextDataId; } /* * ���ñʼǵ�ͨ������ ID�� * @param id ͨ������ ID */ public void setCallDataId(long id) { // ���� NoteData ��� setCallDataId ����������ͨ������ ID mNoteData.setCallDataId(id); } /* * ���õ������ݵķ����� * �÷�����������������һ������һ��ֵ���������Ǵ��ݸ� `mNoteData` ����� `setCallData` ������ * @param key ���ڴ洢���ݵļ��� * @param value ���������ֵ�� */ public void setCallData(String key, String value) { //���� `mNoteData` ����� `setCallData` ���������� `key` �� `value` ��Ϊ�������ݡ� mNoteData.setCallData(key, value); } /* * ����Ƿ��б����ĵķ����� * �÷�������һ������ֵ��ָʾ�Ƿ��б����ġ�����б����ģ��� true������ false�� * �����ĵ��жϻ������������� * 1. `mNoteDiffValues` ���ϵĴ�С�Ƿ���� 0�� * 2. `mNoteData` �����Ƿ汾���ġ� * @return ����б����ģ��� true������ false�� */ public boolean isLocalModified() { // ��� `mNoteDiffValues` ���ϵĴ�С�Ƿ���� 0������ `mNoteData` �����Ƿ汾���ġ� return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified(); } /* * ͬ���ʼǵķ����� * �÷������ڽ������ĵıʼ�����ͬ���������ṩ���С� * @param context Ӧ�ó��������ġ� * @param noteId �ʼǵ�Ψһ��ʶ���� * @return ���ͬ���ɹ����� true������ false�� * @throws IllegalArgumentException ��� noteId С�ڻ���� 0�����׳����쳣�� */ public boolean syncNote(Context context, long noteId) { /// ��� noteId �Ƿ���Ч�������Ч���׳��쳣�� if (noteId <= 0) { throw new IllegalArgumentException("Wrong note id:" + noteId); } // ���û�б����ģ���ֱ�ӷ��� true�� 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 * �����ϣ�һ�����ݷ����仯���ʼ�Ӧ���� {@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"); // Do not return, fall through // �����أ�����ִ�С� } // ��� mNoteDiffValues ���ϡ� mNoteDiffValues.clear(); // ��� mNoteData �б����ģ������������ݵ������ṩ��ʧ�ܣ��� false�� if (mNoteData.isLocalModified() && (mNoteData.pushIntoContentResolver(context, noteId) == null)) { return false; } // ������в����ɹ����� true�� return true; } /* * �ʼ������࣬���ڹ����ʼǵ��ı����ݺ�ͨ�����ݡ� */ private class NoteData { private long mTextDataId;// �ı����ݵ�Ψһ��ʶ�� private ContentValues mTextDataValues;// �ı����ݵ� ContentValues ���� private long mCallDataId; // ͨ�����ݵ�Ψһ��ʶ�� private ContentValues mCallDataValues; // ͨ�����ݵ� ContentValues ���� private static final String TAG = "NoteData";// ��־��ǩ /* * ���캯������ʼ���ı����ݺ�ͨ�����ݵ� ContentValues ���������� ID ����Ϊ 0�� */ 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 С�ڻ���� 0�����׳� IllegalArgumentException �쳣�� * @param id �ı����ݵ�Ψһ��ʶ���� * @throws IllegalArgumentException ��� id С�ڻ���� 0�����׳����쳣�� */ void setTextDataId(long id) { // ��鴫��� id �Ƿ���Ч�������Ч���׳��쳣�� if(id <= 0) { throw new IllegalArgumentException("Text data id should larger than 0"); } mTextDataId = id;// �����ı����ݵ�Ψһ��ʶ���� } /* * ����ͨ�����ݵ�Ψһ��ʶ���� * �÷�����������ͨ�����ݵ�Ψһ��ʶ������������ id С�ڻ���� 0�����׳� IllegalArgumentException �쳣�� * @param id ͨ�����ݵ�Ψһ��ʶ���� * @throws IllegalArgumentException ��� id С�ڻ���� 0�����׳����쳣�� */ void setCallDataId(long id) { // ��鴫��� id �Ƿ���Ч�������Ч���׳��쳣�� if (id <= 0) { throw new IllegalArgumentException("Call data id should larger than 0"); } mCallDataId = id; // ����ͨ�����ݵ�Ψһ��ʶ���� } /* * ����ͨ�����ݵķ����� * �÷������ڽ������ļ�ֵ�Դ洢��ͨ�����ݵ� ContentValues �����У������±ʼǵı�����״̬�������ڡ� * @param key ͨ�����ݵļ��� * @param value ͨ�����ݵ�ֵ�� */ void setCallData(String key, String value) { // �������ļ�ֵ�Դ洢��ͨ�����ݵ� ContentValues �����С� mCallDataValues.put(key, value); // ���±ʼǵı�����״̬Ϊ 1����ʾ�б����ġ� mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); // ���±ʼǵ�������Ϊ��ǰʱ�䡣 mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); } /* *�����ı����ݵķ����� * �÷������ڽ������ļ�ֵ�Դ洢���ı����ݵ� ContentValues �����У������±ʼǵı�����״̬�������ڡ� * @param key �ı����ݵļ��� * @param value �ı����ݵ�ֵ�� */ void setTextData(String key, String value) { // �������ļ�ֵ�Դ洢���ı����ݵ� ContentValues �����С� mTextDataValues.put(key, value); // ���±ʼǵı�����״̬Ϊ 1����ʾ�б����ġ� mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); // ���±ʼǵ�������Ϊ��ǰʱ�䡣 mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); } /* * ���������͵������ṩ�ߵķ����� * �÷������ڽ��ı����ݺ�ͨ���������͵������ṩ���С�����ı����ݻ�ͨ���������ģ�����������µ������ṩ���С� * @param context Ӧ�ó��������ġ� * @param noteId �ʼǵ�Ψһ��ʶ���� * @return ������ͳɹ����� Uri������ null�� * @throws IllegalArgumentException ��� noteId С�ڻ���� 0�����׳����쳣�� */ Uri pushIntoContentResolver(Context context, long noteId) { // ���Ƿ�����ǩ���������˷����ķ������η����������͡��������ƺͲ����б��� /** * Check for safety */ //��� noteId �Ƿ���Ч�������Ч���׳� if (noteId <= 0) { throw new IllegalArgumentException("Wrong note id:" + noteId); } //����һ�������б����������������� ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>(); ContentProviderOperation.Builder builder = null; //����ı��������ģ������ı����ݡ� if(mTextDataValues.size() > 0) { //���ʼ� ID ���ӵ��ı����ݵ� ContentValues �����С� mTextDataValues.put(DataColumns.NOTE_ID, noteId); //����ı����ݵ� ID Ϊ 0����ʾ�������ݣ����뵽�����ṩ���С� 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; } } //����ı����ݵ� ID ��Ϊ 0����ʾ���������ݣ����µ������ṩ���С� else { builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId( Notes.CONTENT_DATA_URI, mTextDataId)); builder.withValues(mTextDataValues); operationList.add(builder.build()); } mTextDataValues.clear();// ����ı����ݵ� ContentValues ���� } // ���ͨ���������ģ�����ͨ�����ݡ� if(mCallDataValues.size() > 0) { mCallDataValues.put(DataColumns.NOTE_ID, noteId); //���ʼ� ID ���ӵ�ͨ�����ݵ� ContentValues �����С� //���ͨ�����ݵ� ID Ϊ 0����ʾ�������ݣ����뵽�����ṩ���С� 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; } } //���ͨ�����ݵ� ID ��Ϊ 0����ʾ���������ݣ����µ������ṩ���С� else { builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId( Notes.CONTENT_DATA_URI, mCallDataId)); builder.withValues(mCallDataValues); operationList.add(builder.build()); } mCallDataValues.clear();//���ͨ�����ݵ� ContentValues ���� } //��������б����в�����ִ������������ 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; } } }