1e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov/*
2e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov * Copyright (C) 2010 The Android Open Source Project
3e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov *
4e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License");
5e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov * you may not use this file except in compliance with the License.
6e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov * You may obtain a copy of the License at
7e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov *
8e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov *      http://www.apache.org/licenses/LICENSE-2.0
9e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov *
10e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov * Unless required by applicable law or agreed to in writing, software
11e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS,
12e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov * See the License for the specific language governing permissions and
14e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov * limitations under the License.
15e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov */
16e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikovpackage com.android.contacts.list;
17e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
18e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikovimport android.content.Context;
193c46291ef057eaf7b7f8ca5971e59bebe734a660Jeff Hamiltonimport android.content.CursorLoader;
20e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikovimport android.database.Cursor;
2114ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onukiimport android.database.CursorWrapper;
22e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikovimport android.net.Uri;
23e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
24e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov/**
25e124722daa8a4b31308d53e3f0457c3b66a20ae5Dmitri Plotnikov * A specialized loader for the Join Contacts UI.  It executes two queries:
26e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov * join suggestions and (optionally) the full contact list.
2714ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki *
2814ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki * This loader also loads the "suggestion" cursor, which can be accessed with:
2914ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki * {@code ((JoinContactLoaderResult) result).suggestionCursor }
30e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov */
31e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikovpublic class JoinContactLoader extends CursorLoader {
32e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
33e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    private String[] mProjection;
34e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    private Uri mSuggestionUri;
3514ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki
3614ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki    /**
3714ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki     * Actual returned class.  It's guaranteed that this loader always returns an instance of this
3814ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki     * class.  This class is needed to tie the lifecycle of the second cursor to that of the
3914ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki     * primary one.
4014ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki     *
4114ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki     * Note we can't change the result type of this loader itself, because CursorLoader
4214ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki     * extends AsyncTaskLoader<Cursor>, not AsyncTaskLoader<? extends Cursor>
4314ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki     */
4414ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki    public static class JoinContactLoaderResult extends CursorWrapper {
4514ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki        public final Cursor suggestionCursor;
4614ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki
4714ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki        public JoinContactLoaderResult(Cursor baseCursor, Cursor suggestionCursor) {
4814ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki            super(baseCursor);
4914ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki            this.suggestionCursor = suggestionCursor;
5014ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki        }
5114ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki
5214ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki        @Override
5314ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki        public void close() {
5414ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki            try {
5574b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner                if (suggestionCursor != null) {
5674b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner                    suggestionCursor.close();
5774b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner                }
5814ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki            } finally {
5974b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner                if (super.getWrappedCursor() != null) {
6074b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner                    super.close();
6174b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner                }
6214ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki            }
6314ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki        }
6414ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki    }
65e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
66e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    public JoinContactLoader(Context context) {
67e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        super(context, null, null, null, null, null);
68e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    }
69e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
70e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    public void setSuggestionUri(Uri uri) {
71e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        this.mSuggestionUri = uri;
72e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    }
73e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
74e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    @Override
75e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    public void setProjection(String[] projection) {
76e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        super.setProjection(projection);
77e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        this.mProjection = projection;
78e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    }
79e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
80e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    @Override
813c46291ef057eaf7b7f8ca5971e59bebe734a660Jeff Hamilton    public Cursor loadInBackground() {
82e124722daa8a4b31308d53e3f0457c3b66a20ae5Dmitri Plotnikov        // First execute the suggestions query, then call super.loadInBackground
83e124722daa8a4b31308d53e3f0457c3b66a20ae5Dmitri Plotnikov        // to load the entire list
8414ca86206ce0a54c316e1062c5ed9ee4dee44674Makoto Onuki        final Cursor suggestionsCursor = getContext().getContentResolver()
85ecd392b81d65a5dd5511b2f96bbedfb5b8157ae7Daisuke Miyakawa                .query(mSuggestionUri, mProjection, null, null, null);
8674b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner        if (suggestionsCursor == null) {
8774b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner            return null;
8874b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner        }
8974b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner        Cursor cursorToClose = suggestionsCursor;
9074b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner        try {
9174b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner            final Cursor baseCursor = super.loadInBackground();
9274b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner            if (baseCursor != null) {
9374b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner                final JoinContactLoaderResult result =
9474b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner                        new JoinContactLoaderResult(baseCursor, suggestionsCursor);
9574b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner                cursorToClose = null;
9674b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner                return result;
9774b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner            }
9874b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner        } finally {
9974b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner            if (cursorToClose != null) {
10074b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner                cursorToClose.close();
10174b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner            }
10274b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner        }
10374b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner        return null;
104e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    }
10574b5d6ce8300ae5009938b8f846688b5950215fbJay Shrauner}
106