Subversion Repositories SmartDukaan

Rev

Rev 4980 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

package in.shop2020.serving.services;


import in.shop2020.model.v1.catalog.InventoryService.Client;
import in.shop2020.model.v1.catalog.InventoryServiceException;
import in.shop2020.model.v1.catalog.status;
import in.shop2020.model.v1.catalog.Item;
import in.shop2020.thrift.clients.CatalogClient;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;
import org.apache.thrift.TException;
import org.apache.thrift.transport.TTransportException;

/**
 * 
 * @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");
                CatalogClient catalogServiceClient;
                try {
                        catalogServiceClient = new CatalogClient();
                        Client client = catalogServiceClient.getClient();
                List<Item> items = new ArrayList<Item>();
                items.addAll(client.getAllItemsByStatus(status.ACTIVE));
                items.addAll(client.getAllItemsByStatus(status.PAUSED));
                items.addAll(client.getAllItemsByStatus(status.PAUSED_BY_RISK));
                Set<Long> processedSet = new HashSet<Long>();
                for(Item item: items){
                        if(!processedSet.contains(item.getCatalogItemId())){
                                processedSet.add(item.getCatalogItemId());
                                addItemName(AutoSuggestService.getProductTitle(item));
                        }
                }
                } catch (TTransportException e) {
                        log.error("Error while making thrift connection", e);
                } catch (InventoryServiceException e) {
                        log.error("Inventory Service exception", e);
                } catch (TException e) {
                        log.error("Thrift exception", e);
                }
                log.info("Done with starting Autosuggest service");
        }

        public static AutoSuggestService getAutoSuggestServiceInstance(){
                return autoSuggestService;
        }

        /**
         * Get the title of the product from catalog service.
         * @param item
         * @return
         */
        private static String getProductTitle(Item item){
                String title = ((item.getBrand() != null) ? item.getBrand().trim() + " " : "")
                + ((item.getModelName() != null) ? item.getModelName().trim() + " " : "")
                + (( item.getModelNumber() != null ) ? item.getModelNumber().trim() : "" );
                title = title.replaceAll("  ", " ");
                return title;
        }
    
        private Node addChars(char[] s, int position, Node node, String string)
    {
        if (node == null) { 
                node = new Node(s[position], null); 
        }
        if (s[position] < node.storedChar) { 
                node.left = addChars(s, position, node.left, string); 
        }
        else if (s[position] > node.storedChar) { 
                node.right = addChars(s, position, node.right, string); 
                }
                else
                {
                        if (position + 1 == s.length) { node.addItem(string); }
                        else { node.center =  addChars(s, position + 1, node.center, string); }
                }
        return node;
    }

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

    /**
     * Add String to the tree
     * @param string
     */
    private void addItemName(String string) {
        if (string == null || string == "") return;
        String[] parts = string.trim().toLowerCase().split("\\s+");
        for(String part : parts){
                addStringPart(part, string);
        }
    }
    
    /**
     * 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);
                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){
                        if(node.center==null){
                                return node;
                        }else{
                                return node.center;
                        }
                    }
                    node = node.center;
                }
            }
            return node;
    }
    
    private void getChildElements(Node node, Set<String>  set){
        if(node == null){
                return;
        }
        if(node.itemSet != null){
                if(node.itemSet != null && !node.itemSet.isEmpty()){
                        set.addAll(node.itemSet);
                }
                return;
        }else{
                getChildElements(node.center, set);     
        }
        getChildElements(node.left, set);
        getChildElements(node.right, set);
    }
    

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

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

class Node
{
        char storedChar;
    Node left, center, right;
    Set<String> itemSet;

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