Subversion Repositories SmartDukaan

Rev

Rev 5084 | Blame | Compare with Previous | Last modification | View Log | RSS feed

package in.shop2020.serving.services;


import in.shop2020.serving.utils.Utils;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

/**
 * 
 * @author rajveer
 * 
 * Auto suggest service will help user to search some term. This is based on turnary search tree. 
 */
public class AutoSuggestService
{
        private Node root;
        private static Logger log = Logger.getLogger(AutoSuggestService.class);
        private static AutoSuggestService autoSuggestService;
        
        static{
                synchronized(AutoSuggestService.class){
                        autoSuggestService = new AutoSuggestService();
                        autoSuggestService.initialize();
                }
        }
        
        private void initialize() {
                log.info("Starting instance of Autosuggest service");
                try {
                        Gson g = new Gson();
                        java.lang.reflect.Type typeOfT = new TypeToken<Map<String, List<String>>>(){}.getType();
                        Map<String, List<String>> synonyms = g.fromJson(FileUtils.readFileToString(new File(Utils.EXPORT_JAVASCRIPT_CONTENT_PATH + "autosuggest.json")), typeOfT);
                        if(synonyms != null){
                                for(Entry<String, List<String>> entry : synonyms.entrySet()){
                                        for(String title : entry.getValue()){
                                                addItemName(title, entry.getKey());
                                        }
                                }
                        }
                } catch (Exception e) {
                        log.error("", e);
                }
                log.info("Done with starting Autosuggest service");
        }

        public static AutoSuggestService getAutoSuggestServiceInstance(){
                return autoSuggestService;
        }

        private Node addChars(char[] s, int position, Node node, String string, String displaystring)
    {
        if (node == null) { 
                node = new Node(s[position], null, null); 
        }
        if (s[position] < node.storedChar) {
                node.left = addChars(s, position, node.left, string, displaystring); 
        }
        else if (s[position] > node.storedChar) {
                node.right = addChars(s, position, node.right, string, displaystring); 
        }
        else {
                if (position + 1 == s.length) {
                        node.addItem(string, displaystring);
                }
                else {
                        node.center =  addChars(s, position + 1, node.center, string, displaystring);
                }
        }
        return node;
    }

    public void addStringPart(String part, String string, String displaystring)
    {
        if (part == null || part == "") return;
        root = addChars(part.toCharArray(), 0, root, string, displaystring);
    }

    /**
     * Add String to the tree
     * @param string
     */
    private void addItemName(String string, String displayString) {
        if (string == null || string == "") return;
        String[] parts = string.trim().toLowerCase().split("\\s+");
        for(String part : parts){
                addStringPart(part, string, displayString);
        }
    }
    
    /**
     * Get list of matching product names.
     * @param str
     * @param resultCount
     * @return
     */
    public List<String> getMatchingQueries(String str, int resultCount){
        Set<String> totalSet = new HashSet<String>();
        String[] parts = str.trim().toLowerCase().split("\\s+");
        for(String part : parts){
                Node node = getPartialMatchNode(part);
                Set<String> set = new HashSet<String>();
                getChildElements(node, set, part);
                if(totalSet.isEmpty()){
                        totalSet.addAll(set);
                }else{
                        totalSet.retainAll(set);
                }
        }
        List<String> items = new ArrayList<String>(totalSet);
        if(items.size() > resultCount){
                return items.subList(0, resultCount-1);
        }else{
                return items;   
        }
    }

    /**
     * Return the node till which we are able to match the word.
     * @param str
     * @return
     */
    private Node getPartialMatchNode(String str){
            char[] s = str.toCharArray();
            int pos = 0;
            Node node = root;
            while (node != null)
            {
                if (s[pos] < node.storedChar) { node = node.left; }
                else if (s[pos] > node.storedChar) { node = node.right; }
                else
                {
                    if (++pos == s.length){
                        return node;
                    }
                    node = node.center;
                }
            }
            return node;
    }
    
    private void getChildElements(Node node, Set<String>  set, String str){
        if(node == null){
                return;
        }
        if(node.itemMap != null && !node.itemMap.isEmpty()){
                for(Entry<String, String> entry : node.itemMap.entrySet()) {
                        String item_name = entry.getKey();
                        String item_displayname = entry.getValue();
                        String ignore_item_name = item_name.toLowerCase();
                        if(ignore_item_name.indexOf(str) != -1){
                                set.add(item_displayname);
                        }
                }
        }
        getChildElements(node.center, set, str);        
        getChildElements(node.left, set, str);
        getChildElements(node.right, set, str);
    }
    

        @Override
        public String toString() {
                return "AutoSuggest [root=" + root + "]";
        }

        public static void main(String[] args) throws Exception {
                AutoSuggestService as = new AutoSuggestService();
                as.addItemName("Nokia N8", "Nokia N");
                as.addItemName("Nokia C5-00", "Nokia C5");
                as.addItemName("Nokia C3-00", "Nokia C3");
                as.addItemName("Nokia X2-01", "Nokia X2");
                as.addItemName("Samsung Galaxy Pro", "Samsung Galaxy Pro");
                as.addItemName("Samsung Galaxy Pop", "Samsung Galaxy Pop");
                as.addItemName("Samsung Galaxy 551 I5510", "Samsung Galaxy 551");
                System.out.println(as.getMatchingQueries("noki", 10));
                System.out.println(as.getMatchingQueries("nok", 10));
                System.out.println(as.getMatchingQueries("Nokia", 10));
                System.out.println(as.getMatchingQueries("n8", 10));
                System.out.println(as.getMatchingQueries("po gala", 10));
        }
}

class Node
{
        char storedChar;
    Node left, center, right;
    Map<String, String> itemMap;

    public void addItem(String itemName, String itemDisplayName){
        if(itemMap == null || itemMap.isEmpty()){
                itemMap = new HashMap<String, String>();
        }
        itemMap.put(itemName, itemDisplayName);
    }
    public Node(char ch, String itemName, String itemDisplayName)
    {
        this.storedChar = ch;
        if(itemName != null){
                itemMap = new HashMap<String, String>();
                itemMap.put(itemName, itemDisplayName);
        }
    }
        @Override
        public String toString() {
                return "Node [storedChar=" + storedChar + ", left=" + left
                                + ", center=" + center + ", right=" + right + ", itemMap="
                                + itemMap + "]";
        }   
}