/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * 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 com.android.vcard;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Entity;
import android.content.Entity.NamedContentValues;
import android.content.EntityIterator;
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.net.Uri;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Event;
import android.provider.ContactsContract.CommonDataKinds.Im;
import android.provider.ContactsContract.CommonDataKinds.Nickname;
import android.provider.ContactsContract.CommonDataKinds.Note;
import android.provider.ContactsContract.CommonDataKinds.Organization;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.Relation;
import android.provider.ContactsContract.CommonDataKinds.SipAddress;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.CommonDataKinds.Website;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.RawContactsEntity;
import android.provider.ContactsContract;
import android.text.TextUtils;
import android.util.Log;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * The class for composing vCard from Contacts information.
 * </p>
 * <p>
 * Usually, this class should be used like this.
 * </p>
 * <pre class="prettyprint">VCardComposer composer = null;
 * try {
 *     composer = new VCardComposer(context);
 *     composer.addHandler(
 *             composer.new HandlerForOutputStream(outputStream));
 *     if (!composer.init()) {
 *         // Do something handling the situation.
 *         return;
 *     }
 *     while (!composer.isAfterLast()) {
 *         if (mCanceled) {
 *             // Assume a user may cancel this operation during the export.
 *             return;
 *         }
 *         if (!composer.createOneEntry()) {
 *             // Do something handling the error situation.
 *             return;
 *         }
 *     }
 * } finally {
 *     if (composer != null) {
 *         composer.terminate();
 *     }
 * }</pre>
 * <p>
 * Users have to manually take care of memory efficiency. Even one vCard may contain
 * image of non-trivial size for mobile devices.
 * </p>
 * <p>
 * {@link VCardBuilder} is used to build each vCard.
 * </p>
 */
public class VCardComposer {
    private static final String LOG_TAG = "VCardComposer";
    private static final boolean DEBUG = false;

    public static final String FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO =
        "Failed to get database information";

    public static final String FAILURE_REASON_NO_ENTRY =
        "There's no exportable in the database";

    public static final String FAILURE_REASON_NOT_INITIALIZED =
        "The vCard composer object is not correctly initialized";

    /** Should be visible only from developers... (no need to translate, hopefully) */
    public static final String FAILURE_REASON_UNSUPPORTED_URI =
        "The Uri vCard composer received is not supported by the composer.";

    public static final String NO_ERROR = "No error";

    // Strictly speaking, "Shift_JIS" is the most appropriate, but we use upper version here,
    // since usual vCard devices for Japanese devices already use it.
    private static final String SHIFT_JIS = "SHIFT_JIS";
    private static final String UTF_8 = "UTF-8";

    private static final Map<Integer, String> sImMap;

    static {
        sImMap = new HashMap<Integer, String>();
        sImMap.put(Im.PROTOCOL_AIM, VCardConstants.PROPERTY_X_AIM);
        sImMap.put(Im.PROTOCOL_MSN, VCardConstants.PROPERTY_X_MSN);
        sImMap.put(Im.PROTOCOL_YAHOO, VCardConstants.PROPERTY_X_YAHOO);
        sImMap.put(Im.PROTOCOL_ICQ, VCardConstants.PROPERTY_X_ICQ);
        sImMap.put(Im.PROTOCOL_JABBER, VCardConstants.PROPERTY_X_JABBER);
        sImMap.put(Im.PROTOCOL_SKYPE, VCardConstants.PROPERTY_X_SKYPE_USERNAME);
        // We don't add Google talk here since it has to be handled separately.
    }

    private final int mVCardType;
    private final ContentResolver mContentResolver;

    private final boolean mIsDoCoMo;
    /**
     * Used only when {@link #mIsDoCoMo} is true. Set to true when the first vCard for DoCoMo
     * vCard is emitted.
     */
    private boolean mFirstVCardEmittedInDoCoMoCase;

    private Cursor mCursor;
    private boolean mCursorSuppliedFromOutside;
    private int mIdColumn;
    private Uri mContentUriForRawContactsEntity;

    private final String mCharset;

    private boolean mInitDone;
    private String mErrorReason = NO_ERROR;

    /**
     * Set to false when one of {@link #init()} variants is called, and set to true when
     * {@link #terminate()} is called. Initially set to true.
     */
    private boolean mTerminateCalled = true;

    private RawContactEntitlesInfoCallback mRawContactEntitlesInfoCallback;

    private static final String[] sContactsProjection = new String[] {
        Contacts._ID,
    };

    public VCardComposer(Context context) {
        this(context, VCardConfig.VCARD_TYPE_DEFAULT, null, true);
    }

    /**
     * The variant which sets charset to null and sets careHandlerErrors to true.
     */
    public VCardComposer(Context context, int vcardType) {
        this(context, vcardType, null, true);
    }

    public VCardComposer(Context context, int vcardType, String charset) {
        this(context, vcardType, charset, true);
    }

    /**
     * The variant which sets charset to null.
     */
    public VCardComposer(final Context context, final int vcardType,
            final boolean careHandlerErrors) {
        this(context, vcardType, null, careHandlerErrors);
    }

    /**
     * Constructs for supporting call log entry vCard composing.
     *
     * @param context Context to be used during the composition.
     * @param vcardType The type of vCard, typically available via {@link VCardConfig}.
     * @param charset The charset to be used. Use null when you don't need the charset.
     * @param careHandlerErrors If true, This object returns false everytime
     */
    public VCardComposer(final Context context, final int vcardType, String charset,
            final boolean careHandlerErrors) {
        this(context, context.getContentResolver(), vcardType, charset, careHandlerErrors);
    }

    /**
     * Just for testing for now.
     * @param resolver {@link ContentResolver} which used by this object.
     * @hide
     */
    public VCardComposer(final Context context, ContentResolver resolver,
            final int vcardType, String charset, final boolean careHandlerErrors) {
        // Not used right now
        // mContext = context;
        mVCardType = vcardType;
        mContentResolver = resolver;

        mIsDoCoMo = VCardConfig.isDoCoMo(vcardType);

        charset = (TextUtils.isEmpty(charset) ? VCardConfig.DEFAULT_EXPORT_CHARSET : charset);
        final boolean shouldAppendCharsetParam = !(
                VCardConfig.isVersion30(vcardType) && UTF_8.equalsIgnoreCase(charset));

        if (mIsDoCoMo || shouldAppendCharsetParam) {
            if (SHIFT_JIS.equalsIgnoreCase(charset)) {
                mCharset = charset;
            } else {
                /* Log.w(LOG_TAG,
                        "The charset \"" + charset + "\" is used while "
                        + SHIFT_JIS + " is needed to be used."); */
                if (TextUtils.isEmpty(charset)) {
                    mCharset = SHIFT_JIS;
                } else {
                    mCharset = charset;
                }
            }
        } else {
            if (TextUtils.isEmpty(charset)) {
                mCharset = UTF_8;
            } else {
                mCharset = charset;
            }
        }

        Log.d(LOG_TAG, "Use the charset \"" + mCharset + "\"");
    }

    /**
     * Initializes this object using default {@link Contacts#CONTENT_URI}.
     *
     * You can call this method or a variant of this method just once. In other words, you cannot
     * reuse this object.
     *
     * @return Returns true when initialization is successful and all the other
     *          methods are available. Returns false otherwise.
     */
    public boolean init() {
        return init(null, null);
    }

    /**
     * Special variant of init(), which accepts a Uri for obtaining {@link RawContactsEntity} from
     * {@link ContentResolver} with {@link Contacts#_ID}.
     * <code>
     * String selection = Data.CONTACT_ID + "=?";
     * String[] selectionArgs = new String[] {contactId};
     * Cursor cursor = mContentResolver.query(
     *         contentUriForRawContactsEntity, null, selection, selectionArgs, null)
     * </code>
     *
     * You can call this method or a variant of this method just once. In other words, you cannot
     * reuse this object.
     *
     * @deprecated Use {@link #init(Uri, String[], String, String[], String, Uri)} if you really
     * need to change the default Uri.
     */
    @Deprecated
    public boolean initWithRawContactsEntityUri(Uri contentUriForRawContactsEntity) {
        return init(Contacts.CONTENT_URI, sContactsProjection, null, null, null,
                contentUriForRawContactsEntity);
    }

    /**
     * Initializes this object using default {@link Contacts#CONTENT_URI} and given selection
     * arguments.
     */
    public boolean init(final String selection, final String[] selectionArgs) {
        return init(Contacts.CONTENT_URI, sContactsProjection, selection, selectionArgs,
                null, null);
    }

    /**
     * Note that this is unstable interface, may be deleted in the future.
     */
    public boolean init(final Uri contentUri, final String selection,
            final String[] selectionArgs, final String sortOrder) {
        return init(contentUri, sContactsProjection, selection, selectionArgs, sortOrder, null);
    }

    /**
     * @param contentUri Uri for obtaining the list of contactId. Used with
     * {@link ContentResolver#query(Uri, String[], String, String[], String)}
     * @param selection selection used with
     * {@link ContentResolver#query(Uri, String[], String, String[], String)}
     * @param selectionArgs selectionArgs used with
     * {@link ContentResolver#query(Uri, String[], String, String[], String)}
     * @param sortOrder sortOrder used with
     * {@link ContentResolver#query(Uri, String[], String, String[], String)}
     * @param contentUriForRawContactsEntity Uri for obtaining entries relevant to each
     * contactId.
     * Note that this is an unstable interface, may be deleted in the future.
     */
    public boolean init(final Uri contentUri, final String selection,
            final String[] selectionArgs, final String sortOrder,
            final Uri contentUriForRawContactsEntity) {
        return init(contentUri, sContactsProjection, selection, selectionArgs, sortOrder,
                contentUriForRawContactsEntity);
    }

    /**
     * A variant of init(). Currently just for testing. Use other variants for init().
     *
     * First we'll create {@link Cursor} for the list of contactId.
     *
     * <code>
     * Cursor cursorForId = mContentResolver.query(
     *         contentUri, projection, selection, selectionArgs, sortOrder);
     * </code>
     *
     * After that, we'll obtain data for each contactId in the list.
     *
     * <code>
     * Cursor cursorForContent = mContentResolver.query(
     *         contentUriForRawContactsEntity, null,
     *         Data.CONTACT_ID + "=?", new String[] {contactId}, null)
     * </code>
     *
     * {@link #createOneEntry()} or its variants let the caller obtain each entry from
     * <code>cursorForContent</code> above.
     *
     * @param contentUri Uri for obtaining the list of contactId. Used with
     * {@link ContentResolver#query(Uri, String[], String, String[], String)}
     * @param projection projection used with
     * {@link ContentResolver#query(Uri, String[], String, String[], String)}
     * @param selection selection used with
     * {@link ContentResolver#query(Uri, String[], String, String[], String)}
     * @param selectionArgs selectionArgs used with
     * {@link ContentResolver#query(Uri, String[], String, String[], String)}
     * @param sortOrder sortOrder used with
     * {@link ContentResolver#query(Uri, String[], String, String[], String)}
     * @param contentUriForRawContactsEntity Uri for obtaining entries relevant to each
     * contactId.
     * @return true when successful
     *
     * @hide
     */
    public boolean init(final Uri contentUri, final String[] projection,
            final String selection, final String[] selectionArgs,
            final String sortOrder, Uri contentUriForRawContactsEntity) {
        if (!ContactsContract.AUTHORITY.equals(contentUri.getAuthority())) {
            if (DEBUG) Log.d(LOG_TAG, "Unexpected contentUri: " + contentUri);
            mErrorReason = FAILURE_REASON_UNSUPPORTED_URI;
            return false;
        }

        if (!initInterFirstPart(contentUriForRawContactsEntity)) {
            return false;
        }
        if (!initInterCursorCreationPart(contentUri, projection, selection, selectionArgs,
                sortOrder)) {
            return false;
        }
        if (!initInterMainPart()) {
            return false;
        }
        return initInterLastPart();
    }

    /**
     * Just for testing for now. Do not use.
     * @hide
     */
    public boolean init(Cursor cursor) {
        return initWithCallback(cursor, null);
    }

    /**
    * @param cursor Cursor that used to get contact id
    * @param rawContactEntitlesInfoCallback Callback that return RawContactEntitlesInfo
    * Note that this is an unstable interface, may be deleted in the future.
    *
    * @return true when successful
    */
    public boolean initWithCallback(Cursor cursor,
            RawContactEntitlesInfoCallback rawContactEntitlesInfoCallback) {
        if (!initInterFirstPart(null)) {
            return false;
        }
        mCursorSuppliedFromOutside = true;
        mCursor = cursor;
        mRawContactEntitlesInfoCallback = rawContactEntitlesInfoCallback;
        if (!initInterMainPart()) {
            return false;
        }
        return initInterLastPart();
    }

    private boolean initInterFirstPart(Uri contentUriForRawContactsEntity) {
        mContentUriForRawContactsEntity =
                (contentUriForRawContactsEntity != null ? contentUriForRawContactsEntity :
                        RawContactsEntity.CONTENT_URI);
        if (mInitDone) {
            Log.e(LOG_TAG, "init() is already called");
            return false;
        }
        return true;
    }

    private boolean initInterCursorCreationPart(
            final Uri contentUri, final String[] projection,
            final String selection, final String[] selectionArgs, final String sortOrder) {
        mCursorSuppliedFromOutside = false;
        mCursor = mContentResolver.query(
                contentUri, projection, selection, selectionArgs, sortOrder);
        if (mCursor == null) {
            Log.e(LOG_TAG, String.format("Cursor became null unexpectedly"));
            mErrorReason = FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO;
            return false;
        }
        return true;
    }

    private boolean initInterMainPart() {
        if (mCursor.getCount() == 0 || !mCursor.moveToFirst()) {
            if (DEBUG) {
                Log.d(LOG_TAG,
                    String.format("mCursor has an error (getCount: %d): ", mCursor.getCount()));
            }
            mErrorReason = FAILURE_REASON_NO_ENTRY;
            closeCursorIfAppropriate();
            return false;
        }
        mIdColumn = mCursor.getColumnIndex(Data.CONTACT_ID);
        if (mIdColumn < 0) {
            mIdColumn = mCursor.getColumnIndex(Contacts._ID);
        }
        return mIdColumn >= 0;
    }

    private boolean initInterLastPart() {
        mInitDone = true;
        mTerminateCalled = false;
        return true;
    }

    /**
     * @return a vCard string.
     */
    public String createOneEntry() {
        return createOneEntry(null);
    }

    /**
     * @hide
     */
    public String createOneEntry(Method getEntityIteratorMethod) {
        if (mIsDoCoMo && !mFirstVCardEmittedInDoCoMoCase) {
            mFirstVCardEmittedInDoCoMoCase = true;
            // Previously we needed to emit empty data for this specific case, but actually
            // this doesn't work now, as resolver doesn't return any data with "-1" contactId.
            // TODO: re-introduce or remove this logic. Needs to modify unit test when we
            // re-introduce the logic.
            // return createOneEntryInternal("-1", getEntityIteratorMethod);
        }

        final String vcard = createOneEntryInternal(mCursor.getLong(mIdColumn),
                getEntityIteratorMethod);
        if (!mCursor.moveToNext()) {
            Log.e(LOG_TAG, "Cursor#moveToNext() returned false");
        }
        return vcard;
    }

    /**
     *  Class that store rawContactEntitlesUri and contactId
     */
    public static class RawContactEntitlesInfo {
        public final Uri rawContactEntitlesUri;
        public final long contactId;
        public RawContactEntitlesInfo(Uri rawContactEntitlesUri, long contactId) {
            this.rawContactEntitlesUri = rawContactEntitlesUri;
            this.contactId = contactId;
        }
    }

    /**
    * Listener for getting raw contact entitles info
    */
    public interface RawContactEntitlesInfoCallback {
        /**
        * Callback to get RawContactEntitlesInfo from contact id
        *
        * @param contactId Contact id that you want to process.
        * @return RawContactEntitlesInfo that ready to process.
        */
        RawContactEntitlesInfo getRawContactEntitlesInfo(long contactId);
    }

    private String createOneEntryInternal(long contactId,
            final Method getEntityIteratorMethod) {
        final Map<String, List<ContentValues>> contentValuesListMap =
                new HashMap<String, List<ContentValues>>();
        // The resolver may return the entity iterator with no data. It is possible.
        // e.g. If all the data in the contact of the given contact id are not exportable ones,
        //      they are hidden from the view of this method, though contact id itself exists.
        EntityIterator entityIterator = null;
        try {
            Uri uri = mContentUriForRawContactsEntity;
            if (mRawContactEntitlesInfoCallback != null) {
                RawContactEntitlesInfo rawContactEntitlesInfo =
                        mRawContactEntitlesInfoCallback.getRawContactEntitlesInfo(contactId);
                uri = rawContactEntitlesInfo.rawContactEntitlesUri;
                contactId = rawContactEntitlesInfo.contactId;
            }
            final String selection = Data.CONTACT_ID + "=?";
            final String[] selectionArgs = new String[] {String.valueOf(contactId)};
            if (getEntityIteratorMethod != null) {
                // Please note that this branch is executed by unit tests only
                try {
                    entityIterator = (EntityIterator)getEntityIteratorMethod.invoke(null,
                            mContentResolver, uri, selection, selectionArgs, null);
                } catch (IllegalArgumentException e) {
                    Log.e(LOG_TAG, "IllegalArgumentException has been thrown: " +
                            e.getMessage());
                } catch (IllegalAccessException e) {
                    Log.e(LOG_TAG, "IllegalAccessException has been thrown: " +
                            e.getMessage());
                } catch (InvocationTargetException e) {
                    Log.e(LOG_TAG, "InvocationTargetException has been thrown: ", e);
                    throw new RuntimeException("InvocationTargetException has been thrown");
                }
            } else {
                entityIterator = RawContacts.newEntityIterator(mContentResolver.query(
                        uri, null, selection, selectionArgs, null));
            }

            if (entityIterator == null) {
                Log.e(LOG_TAG, "EntityIterator is null");
                return "";
            }

            if (!entityIterator.hasNext()) {
                Log.w(LOG_TAG, "Data does not exist. contactId: " + contactId);
                return "";
            }

            while (entityIterator.hasNext()) {
                Entity entity = entityIterator.next();
                for (NamedContentValues namedContentValues : entity.getSubValues()) {
                    ContentValues contentValues = namedContentValues.values;
                    String key = contentValues.getAsString(Data.MIMETYPE);
                    if (key != null) {
                        List<ContentValues> contentValuesList =
                                contentValuesListMap.get(key);
                        if (contentValuesList == null) {
                            contentValuesList = new ArrayList<ContentValues>();
                            contentValuesListMap.put(key, contentValuesList);
                        }
                        contentValuesList.add(contentValues);
                    }
                }
            }
        } finally {
            if (entityIterator != null) {
                entityIterator.close();
            }
        }

        return buildVCard(contentValuesListMap);
    }

    private VCardPhoneNumberTranslationCallback mPhoneTranslationCallback;
    /**
     * <p>
     * Set a callback for phone number formatting. It will be called every time when this object
     * receives a phone number for printing.
     * </p>
     * <p>
     * When this is set {@link VCardConfig#FLAG_REFRAIN_PHONE_NUMBER_FORMATTING} will be ignored
     * and the callback should be responsible for everything about phone number formatting.
     * </p>
     * <p>
     * Caution: This interface will change. Please don't use without any strong reason.
     * </p>
     */
    public void setPhoneNumberTranslationCallback(VCardPhoneNumberTranslationCallback callback) {
        mPhoneTranslationCallback = callback;
    }

    /**
     * Builds and returns vCard using given map, whose key is CONTENT_ITEM_TYPE defined in
     * {ContactsContract}. Developers can override this method to customize the output.
     */
    public String buildVCard(final Map<String, List<ContentValues>> contentValuesListMap) {
        if (contentValuesListMap == null) {
            Log.e(LOG_TAG, "The given map is null. Ignore and return empty String");
            return "";
        } else {
            final VCardBuilder builder = new VCardBuilder(mVCardType, mCharset);
            builder.appendNameProperties(contentValuesListMap.get(
                    StructuredName.CONTENT_ITEM_TYPE))
                    .appendPhones(contentValuesListMap.get(Phone.CONTENT_ITEM_TYPE),
                            mPhoneTranslationCallback)
                    .appendRelation(contentValuesListMap.get(Relation.CONTENT_ITEM_TYPE))
                    .appendIms(contentValuesListMap.get(Im.CONTENT_ITEM_TYPE))
                    .appendSipAddresses(contentValuesListMap.get(SipAddress.CONTENT_ITEM_TYPE));

            if ((mVCardType & VCardConfig.FLAG_REFRAIN_NICKNAME_EXPORT) == 0) {
                builder.appendNickNames(contentValuesListMap.get(Nickname.CONTENT_ITEM_TYPE));
            }
            if ((mVCardType & VCardConfig.FLAG_REFRAIN_EMAIL_EXPORT) == 0) {
                builder.appendEmails(contentValuesListMap.get(Email.CONTENT_ITEM_TYPE));
            }
            if ((mVCardType & VCardConfig.FLAG_REFRAIN_ADDRESS_EXPORT) == 0) {
                builder.appendPostals(contentValuesListMap.get(
                        StructuredPostal.CONTENT_ITEM_TYPE));
            }
            if ((mVCardType & VCardConfig.FLAG_REFRAIN_ORGANIZATION_EXPORT) == 0) {
                builder.appendOrganizations(contentValuesListMap.get(
                        Organization.CONTENT_ITEM_TYPE));
            }
            if ((mVCardType & VCardConfig.FLAG_REFRAIN_WEBSITES_EXPORT) == 0) {
                builder.appendWebsites(contentValuesListMap.get(Website.CONTENT_ITEM_TYPE));
            }
            if ((mVCardType & VCardConfig.FLAG_REFRAIN_IMAGE_EXPORT) == 0) {
                builder.appendPhotos(contentValuesListMap.get(Photo.CONTENT_ITEM_TYPE));
            }
            if ((mVCardType & VCardConfig.FLAG_REFRAIN_NOTES_EXPORT) == 0) {
                builder.appendNotes(contentValuesListMap.get(Note.CONTENT_ITEM_TYPE));
            }
            if ((mVCardType & VCardConfig.FLAG_REFRAIN_EVENTS_EXPORT) == 0) {
                builder.appendEvents(contentValuesListMap.get(Event.CONTENT_ITEM_TYPE));
            }
            return builder.toString();
        }
    }

    public void terminate() {
        closeCursorIfAppropriate();
        mTerminateCalled = true;
    }

    private void closeCursorIfAppropriate() {
        if (!mCursorSuppliedFromOutside && mCursor != null) {
            try {
                mCursor.close();
            } catch (SQLiteException e) {
                Log.e(LOG_TAG, "SQLiteException on Cursor#close(): " + e.getMessage());
            }
            mCursor = null;
        }
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            if (!mTerminateCalled) {
                Log.e(LOG_TAG, "finalized() is called before terminate() being called");
            }
        } finally {
            super.finalize();
        }
    }

    /**
     * @return returns the number of available entities. The return value is undefined
     * when this object is not ready yet (typically when {{@link #init()} is not called
     * or when {@link #terminate()} is already called).
     */
    public int getCount() {
        if (mCursor == null) {
            Log.w(LOG_TAG, "This object is not ready yet.");
            return 0;
        }
        return mCursor.getCount();
    }

    /**
     * @return true when there's no entity to be built. The return value is undefined
     * when this object is not ready yet.
     */
    public boolean isAfterLast() {
        if (mCursor == null) {
            Log.w(LOG_TAG, "This object is not ready yet.");
            return false;
        }
        return mCursor.isAfterLast();
    }

    /**
     * @return Returns the error reason.
     */
    public String getErrorReason() {
        return mErrorReason;
    }
}
