Extending SuggestOracle.Response to pass along "isTruncated" information with the suggestion list.

Review at http://gwt-code-reviews.appspot.com/873801

Review by: jlabanca@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@8800 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/ui/MultiWordSuggestOracle.java b/user/src/com/google/gwt/user/client/ui/MultiWordSuggestOracle.java
index 645dc23..ca92bb1 100644
--- a/user/src/com/google/gwt/user/client/ui/MultiWordSuggestOracle.java
+++ b/user/src/com/google/gwt/user/client/ui/MultiWordSuggestOracle.java
@@ -219,9 +219,25 @@
 
   @Override
   public void requestSuggestions(Request request, Callback callback) {
-    final List<MultiWordSuggestion> suggestions = computeItemsFor(
-        request.getQuery(), request.getLimit());
+    String query = normalizeSearch(request.getQuery());
+    int limit = request.getLimit();
+
+    // Get candidates from search words.
+    List<String> candidates = createCandidatesFromSearch(query);
+
+    // Respect limit for number of choices.
+    int numberTruncated = Math.max(0, candidates.size() - limit);
+    for (int i = candidates.size() - 1; i > limit; i--) {
+      candidates.remove(i);
+    }
+
+    // Convert candidates to suggestions.
+    List<MultiWordSuggestion> suggestions = 
+        convertToFormattedSuggestions(query, candidates);
+
     Response response = new Response(suggestions);
+    response.setMoreSuggestionsCount(numberTruncated);
+
     callback.onSuggestionsReady(request, response);
   }
 
@@ -271,23 +287,6 @@
   }
 
   /**
-   * Compute the suggestions that are matches for a given query.
-   * 
-   * @param query search string
-   * @param limit limit
-   * @return matching suggestions
-   */
-  private List<MultiWordSuggestion> computeItemsFor(String query, int limit) {
-    query = normalizeSearch(query);
-
-    // Get candidates from search words.
-    List<String> candidates = createCandidatesFromSearch(query, limit);
-
-    // Convert candidates to suggestions.
-    return convertToFormattedSuggestions(query, candidates);
-  }
-
-  /**
    * Returns real suggestions with the given query in <code>strong</code> html
    * font.
    * 
@@ -344,7 +343,7 @@
   /**
    * Find the sorted list of candidates that are matches for the given query.
    */
-  private List<String> createCandidatesFromSearch(String query, int limit) {
+  private List<String> createCandidatesFromSearch(String query) {
     ArrayList<String> candidates = new ArrayList<String>();
 
     if (query.length() == 0) {
@@ -381,10 +380,6 @@
     if (candidateSet != null) {
       candidates.addAll(candidateSet);
       Collections.sort(candidates);
-      // Respect limit for number of choices.
-      for (int i = candidates.size() - 1; i > limit; i--) {
-        candidates.remove(i);
-      }
     }
     return candidates;
   }
diff --git a/user/src/com/google/gwt/user/client/ui/SuggestOracle.java b/user/src/com/google/gwt/user/client/ui/SuggestOracle.java
index 5218ff3..2941353 100644
--- a/user/src/com/google/gwt/user/client/ui/SuggestOracle.java
+++ b/user/src/com/google/gwt/user/client/ui/SuggestOracle.java
@@ -119,11 +119,32 @@
 
   /**
    * {@link com.google.gwt.user.client.ui.SuggestOracle} response.
+   * 
+   * <p>Can optionally have truncation information provided. To indicate that
+   * there are more results but the number is not known, use:
+   * 
+   * <p><code>response.setMoreSuggestions(true);</code>
+   * 
+   * <p>Or to indicate more results with an exact number, use:
+   * 
+   * <p><code>response.setMoreSuggestionsCount(102);</code>
    */
   public static class Response implements IsSerializable {
     private Collection<? extends Suggestion> suggestions;
 
     /**
+     * The response is considered to have "more suggestions" when the number of 
+     * matching suggestions exceeds {@link Request#getLimit}, so the response
+     * suggestion list is truncated.
+     */
+    private boolean moreSuggestions = false;
+
+    /**
+     * Number of truncated suggestions.
+     */
+    private int numMoreSuggestions = 0;
+
+    /**
      * Constructor for {@link Response}.
      */
     public Response() {
@@ -140,6 +161,16 @@
     }
 
     /**
+     * Gets how many more suggestions there are.
+     * 
+     * @return the count. if there no more suggestions or the number of more
+     *         suggestions is unknown, returns 0.
+     */
+    public int getMoreSuggestionsCount() {
+      return this.numMoreSuggestions;
+    }
+    
+    /**
      * Gets the collection of suggestions. Each suggestion must implement the
      * {@link Suggestion} interface.
      * 
@@ -150,6 +181,36 @@
     }
 
     /**
+     * Gets whether or not the suggestion list was truncated due to the
+     * {@Request#getLimit}.
+     */
+    public boolean hasMoreSuggestions() {
+      return this.moreSuggestions;
+    }
+
+    /**
+     * Sets whether or not the suggestion list was truncated due to the
+     * {@Request#getLimit}.
+     */
+    public void setMoreSuggestions(boolean moreSuggestions) {
+      this.moreSuggestions = moreSuggestions;
+    }
+
+    /**
+     * Sets whether or not the suggestion list was truncated due to the
+     * {@Request#getLimit}, by providing an exact count of remaining 
+     * suggestions.
+     * 
+     * @param count number of truncated suggestions. Pass 0 to indicate there
+     *        are no other suggestions, which is equivlent to 
+     *        {@link #setMoreSuggestions(false)}.
+     */
+    public void setMoreSuggestionsCount(int count) {
+      this.numMoreSuggestions = count;
+      this.moreSuggestions = (count > 0);
+    }
+
+    /**
      * Sets the suggestions for this response. Each suggestion must implement
      * the {@link Suggestion} interface.
      *