Home | History | Annotate | Download | only in quicksearchbox
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.quicksearchbox;
     18 
     19 import com.android.quicksearchbox.util.NamedTask;
     20 import com.android.quicksearchbox.util.NamedTaskExecutor;
     21 
     22 import android.util.Log;
     23 
     24 import java.util.Collections;
     25 import java.util.HashSet;
     26 import java.util.Set;
     27 
     28 /**
     29  * Refreshes shortcuts from their source.
     30  */
     31 class SourceShortcutRefresher implements ShortcutRefresher {
     32     private static final String TAG = "QSB.SourceShortcutRefresher";
     33     private static final boolean DBG = false;
     34 
     35     private final NamedTaskExecutor mExecutor;
     36 
     37     private final Set<String> mRefreshed = Collections.synchronizedSet(new HashSet<String>());
     38     private final Set<String> mRefreshing = Collections.synchronizedSet(new HashSet<String>());
     39 
     40     /**
     41      * Create a ShortcutRefresher that will refresh shortcuts using the given executor.
     42      *
     43      * @param executor Used to execute the tasks.
     44      */
     45     public SourceShortcutRefresher(NamedTaskExecutor executor) {
     46         mExecutor = executor;
     47     }
     48 
     49     public void refresh(Suggestion shortcut, Listener listener) {
     50         Source source = shortcut.getSuggestionSource();
     51         if (source == null) {
     52             throw new NullPointerException("source");
     53         }
     54         String shortcutId = shortcut.getShortcutId();
     55         if (shouldRefresh(source, shortcutId) && !isRefreshing(source, shortcutId)) {
     56             if (DBG) {
     57                 Log.d(TAG, "Refreshing shortcut  " + shortcutId + " '" +
     58                         shortcut.getSuggestionText1() + "'");
     59             }
     60             markShortcutRefreshing(source, shortcutId);
     61             String extraData = shortcut.getSuggestionIntentExtraData();
     62             ShortcutRefreshTask refreshTask = new ShortcutRefreshTask(
     63                     source, shortcutId, extraData, listener);
     64             mExecutor.execute(refreshTask);
     65         }
     66     }
     67 
     68     /**
     69      * Returns true if the given shortcut requires refreshing.
     70      */
     71     public boolean shouldRefresh(Source source, String shortcutId) {
     72         return source != null && shortcutId != null
     73                 && !mRefreshed.contains(makeKey(source, shortcutId));
     74     }
     75 
     76     public boolean isRefreshing(Source source, String shortcutId) {
     77         return source != null && shortcutId != null
     78                 && mRefreshing.contains(makeKey(source, shortcutId));
     79     }
     80 
     81     private void markShortcutRefreshing(Source source, String shortcutId) {
     82         mRefreshing.add(makeKey(source, shortcutId));
     83     }
     84 
     85     /**
     86      * Indicate that the shortcut no longer requires refreshing.
     87      */
     88     public void markShortcutRefreshed(Source source, String shortcutId) {
     89         String key = makeKey(source, shortcutId);
     90         mRefreshed.add(key);
     91         mRefreshing.remove(key);
     92     }
     93 
     94     /**
     95      * Reset internal state.  This results in all shortcuts requiring refreshing.
     96      */
     97     public void reset() {
     98         mRefreshed.clear();
     99     }
    100 
    101     private static String makeKey(Source source, String shortcutId) {
    102         return source.getName() + "#" + shortcutId;
    103     }
    104 
    105     /**
    106      * Refreshes a shortcut with a source and reports the result to a
    107      * {@link ShortcutRefresher.Listener}.
    108      */
    109     private class ShortcutRefreshTask implements NamedTask {
    110         private final Source mSource;
    111         private final String mShortcutId;
    112         private final String mExtraData;
    113         private final Listener mListener;
    114 
    115         /**
    116          * @param source The source that should validate the shortcut.
    117          * @param shortcutId The shortcut to be refreshed.
    118          * @param listener Who to report back to when the result is in.
    119          */
    120         ShortcutRefreshTask(Source source, String shortcutId, String extraData,
    121                 Listener listener) {
    122             mSource = source;
    123             mShortcutId = shortcutId;
    124             mExtraData = extraData;
    125             mListener = listener;
    126         }
    127 
    128         public String getName() {
    129             return mSource.getName();
    130         }
    131 
    132         public void run() {
    133             // TODO: Add latency tracking and logging.
    134             SuggestionCursor refreshed = mSource.refreshShortcut(mShortcutId, mExtraData);
    135             // Close cursor if empty and pass null as the refreshed cursor
    136             if (refreshed != null && refreshed.getCount() == 0) {
    137                 refreshed.close();
    138                 refreshed = null;
    139             }
    140             markShortcutRefreshed(mSource, mShortcutId);
    141             mListener.onShortcutRefreshed(mSource, mShortcutId, refreshed);
    142         }
    143 
    144     }
    145 }
    146