ListSuggestionCursorNoDuplicates.java revision 93bd2e70b8b08da1ec37fd0e990dac05551d2e90
1/*
2 * Copyright (C) 2009 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
17package com.android.quicksearchbox;
18
19import android.util.Log;
20
21import java.util.HashSet;
22
23/**
24 * A SuggestionCursor that is backed by a list of SuggestionPosition objects
25 * and doesn't allow duplicate suggestions.
26 */
27public class ListSuggestionCursorNoDuplicates extends ListSuggestionCursor {
28
29    private static final boolean DBG = false;
30    private static final String TAG = "QSB.ListSuggestionCursorNoDuplicates";
31
32    private final HashSet<String> mSuggestionKeys;
33
34    public ListSuggestionCursorNoDuplicates(String userQuery) {
35        super(userQuery);
36        mSuggestionKeys = new HashSet<String>();
37    }
38
39    @Override
40    public boolean add(Suggestion suggestion) {
41        String key = getSuggestionKey(suggestion);
42        if (mSuggestionKeys.add(key)) {
43            return super.add(suggestion);
44        } else {
45            if (DBG) Log.d(TAG, "Rejecting duplicate " + key);
46            return false;
47        }
48    }
49
50    /**
51     * Gets a unique key that identifies a suggestion. This is used to avoid
52     * duplicate suggestions in the promoted list.
53     */
54    private String getSuggestionKey(Suggestion suggestion) {
55        String action = makeKeyComponent(suggestion.getSuggestionIntentAction());
56        String data = makeKeyComponent(normalizeUrl(suggestion.getSuggestionIntentDataString()));
57        String query = makeKeyComponent(normalizeUrl(suggestion.getSuggestionQuery()));
58        // calculating accurate size of string builder avoids an allocation vs starting with
59        // the default size and having to expand.
60        int size = action.length() + 2 + data.length() + query.length();
61        return new StringBuilder(size)
62                .append(action)
63                .append('#')
64                .append(data)
65                .append('#')
66                .append(query)
67                .toString();
68    }
69
70    private String makeKeyComponent(String str) {
71        return str == null ? "" : str;
72    }
73
74    /** Simple url normalization that strips http:// and empty paths, i.e.,
75     *  http://www.google.com/ -> www.google.com.  Used to prevent obvious
76     * duplication of nav suggestions, bookmarks and urls entered by the user.
77     */
78    private static String normalizeUrl(String url) {
79        if (url != null && url.startsWith("http://")) {
80            int start = 7;   // length of http://
81            int end = url.length();
82            if (url.indexOf('/', start) == end - 1) {
83                end--;
84            }
85            return url.substring(start, end);
86        }
87        return url;
88    }
89
90}
91