// Copyright 2009 Google Inc.
//
// 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.google.android.stardroid.search;

import java.util.*;

/**
 * Given a set of strings such as search terms, this class allows you to search
 * for that string by prefix.
 * @author John Taylor
 *
 */
public class PrefixStore {

  static private class TrieNode {
    Map<Character, TrieNode> children = new HashMap<>();

    // we need to stored the originals as to support insensitive case searching
    Set<String> results = new HashSet<>();
  }

  private TrieNode root = new TrieNode();

  private static final Set<String> EMPTY_SET = Collections.unmodifiableSet(new HashSet<String>());

  /**
   * Search for any queries matching this prefix.  Note that the prefix is
   * case-independent.
   *
   * TODO(@tcao) refactor this API. Search should return a relevance ranked list.
   */
  public Set<String> queryByPrefix(String prefix) {
    prefix = prefix.toLowerCase();
    TrieNode n = root;
    for (int i = 0; i < prefix.length(); i++) {
      TrieNode c = n.children.get(prefix.charAt(i));
      if (c == null) {
        return EMPTY_SET;
      }
      n = c;
    }
    Set<String> coll = new HashSet<String>();
    collect(n, coll);
    return coll;
  }

  private void collect(TrieNode n, Collection<String> coll) {
    coll.addAll(n.results);
    for (Character ch : n.children.keySet()) {
      collect(n.children.get(ch), coll);
    }
  }

  /**
   * Put a new string in the store.
   */
  public void add(String string) {
    TrieNode n = root;
    String lower = string.toLowerCase();
    for (int i = 0; i < lower.length(); i++) {
      TrieNode c = n.children.get(lower.charAt(i));
      if (c == null) {
        c = new TrieNode();
        n.children.put(lower.charAt(i), c);
      }
      n = c;
    }
    n.results.add(string);
  }

  /**
   * Put a whole load of objects in the store at once.
   * @param strings a collection of strings.
   */
  public void addAll(Collection<String> strings) {
    for (String string : strings) {
      add(string);
    }
  }
}

// Copyright 2009 Google Inc.
//
// 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.google.android.stardroid.search;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Given a set of strings such as search terms, this class allows you to search
 * for that string by prefix.
 * @author John Taylor
 *
 */
public class PrefixStore {

  static private class TrieNode {
    Map<Character, TrieNode> children = new HashMap<>();

    // we need to store the originals to support insensitive case searching
    Set<String> results = new HashSet<>();
  }

  private TrieNode root = new TrieNode();

  private static final Set<String> EMPTY_SET = Collections.unmodifiableSet(new HashSet<String>());

  /**
   * Search for any queries matching this prefix.  Note that the prefix is
   * case-independent.
   *
   * TODO(@tcao) refactor this API. Search should return a relevance ranked list.
   */
  public Set<String> queryByPrefix(String prefix) {
    prefix = prefix.toLowerCase();
    TrieNode n = root;
    for (int i = 0; i < prefix.length(); i++) {
      TrieNode c = n.children.get(prefix.charAt(i));
      if (c == null) {
        return EMPTY_SET;
      }
      n = c;
    }
    Set<String> coll = new HashSet<String>();
    collect(n, coll);
    return coll;
  }

  private void collect(TrieNode n, Collection<String> coll) {
    coll.addAll(n.results);
    for (Character ch : n.children.keySet()) {
      collect(n.children.get(ch), coll);
    }
  }

  /**
   * Put a new string in the store.
   */
  public void add(String string) {
    TrieNode n = root;
    String lower = string.toLowerCase();
    for (int i = 0; i < lower.length(); i++) {
      TrieNode c = n.children.get(lower.charAt(i));
      if (c == null) {
        c = new TrieNode();
        n.children.put(lower.charAt(i), c);
      }
      n = c;
    }
    n.results.add(string);
  }

  /**
   * Put a whole load of objects in the store at once.
   * @param strings a collection of strings.
   */
  public void addAll(Collection<String> strings) {
    for (String string : strings) {
      add(string);
    }
  }
}

Expand imports