ca.mcgill.cs.creco.logic.ConcreteServiceFacade.java Source code

Java tutorial

Introduction

Here is the source code for ca.mcgill.cs.creco.logic.ConcreteServiceFacade.java

Source

/**
 * Copyright 2014 McGill University
 * 
 * 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 ca.mcgill.cs.creco.logic;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.ui.Model;

import ca.mcgill.cs.creco.data.Category;
import ca.mcgill.cs.creco.data.IDataStore;
import ca.mcgill.cs.creco.data.Product;
import ca.mcgill.cs.creco.data.TypedValue;
import ca.mcgill.cs.creco.logic.search.ICategorySearch;
import ca.mcgill.cs.creco.logic.search.ProductSort;
import ca.mcgill.cs.creco.web.model.ExplanationView;
import ca.mcgill.cs.creco.web.model.FeatureView;
import ca.mcgill.cs.creco.web.model.ProductView;
import ca.mcgill.cs.creco.web.model.UserData;
import ca.mcgill.cs.creco.web.model.UserFeaturesModel;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;

/**
 * Default implementation of the service layer.
 */
@Component
public class ConcreteServiceFacade implements ServiceFacade {
    private static final int MIN_NUMBER_OF_TYPED_LETTERS = 2;
    private static final int NUMBER_OF_FEATURES_TO_DISPLAY = 10;

    @Autowired
    private IDataStore aDataStore;

    @Autowired
    private ICategorySearch aCategorySearch;

    @Autowired
    private ProductRanker aProductRanker;

    @Autowired
    private AttributeExtractor aAttributeExtractor;

    @Autowired
    private ProductSort aProductSort;

    @Override
    public String getCompletions(String pInput) {
        if (pInput.length() <= MIN_NUMBER_OF_TYPED_LETTERS) {
            return "";
        }
        String[] result_set = new String[100];
        int pointer = 0;
        String temp = new String("");
        int index = 0;
        JSONArray response = new JSONArray();
        JSONObject obj = new JSONObject();

        for (Category category : aDataStore.getCategories()) {
            if (category.getNumberOfProducts() == 0) {
                continue;
            }
            if (category.getName().toLowerCase().contains(pInput.toLowerCase())) {
                result_set[pointer++] = category.getName().toLowerCase();
                result_set[pointer++] = "Category";
            }
        }
        Set<String> collectedbrandstillnow = new HashSet<String>();
        Set<String> collectedtexttillnow = new HashSet<String>();
        Set<String> brands = new HashSet<String>();
        Set<String> textSearch = new HashSet<String>();
        for (Product productname : aDataStore.getProducts()) {
            if (productname.getName().toLowerCase().contains(pInput.toLowerCase())) {
                for (String productspace : productname.getName().toLowerCase().split(" ")) {
                    if (productspace.contains(pInput.toLowerCase())) {
                        if (productspace.equals(productname.getBrandName().toLowerCase())) {
                            if (collectedbrandstillnow.contains(productspace)) {

                            } else {
                                collectedbrandstillnow.add(productspace);
                                brands.add(productspace);
                            }
                        } else if (collectedtexttillnow.contains(productspace)
                                || collectedbrandstillnow.contains(productspace)) {
                        } else {
                            collectedtexttillnow.add(productspace);
                            int count = 0;
                            for (int i = 0; i < productspace.length(); i++) {
                                if (Character.isDigit(productspace.charAt(i))) {
                                    count++;
                                }
                            }
                            if (count < 2 && !productspace.contains("(") && !productspace.contains(")")) {
                                textSearch.add(productspace);
                            }
                        }
                    }
                }
            }
        }

        for (String brandname : brands) {
            if (Arrays.asList(result_set).contains(brandname)) {
                index = Arrays.asList(result_set).indexOf(brandname);
                result_set[index + 1] = result_set[index + 1].concat("|Brand");
                temp = result_set[0];
                result_set[0] = result_set[index];
                result_set[index] = temp;
                temp = result_set[1];
                result_set[1] = result_set[index + 1];
                result_set[index + 1] = temp;
            } else {
                result_set[pointer++] = brandname;
                result_set[pointer++] = "Brand";
            }
        }
        for (String textname : textSearch) {
            if (Arrays.asList(result_set).contains(textname)) {
                index = Arrays.asList(result_set).indexOf(textname);
                result_set[index + 1] = result_set[index + 1].concat("|Product");
                temp = result_set[0];
                result_set[0] = result_set[index];
                result_set[index] = temp;
                temp = result_set[1];
                result_set[1] = result_set[index + 1];
                result_set[index + 1] = temp;
            } else {
                result_set[pointer++] = textname;
                result_set[pointer++] = "Product";
            }
        }

        for (index = 0; index < result_set.length; index = index + 2) {
            obj.put("name", result_set[index]);
            obj.put("type", result_set[index + 1]);
            response.add(obj);
            obj = new JSONObject();
        }
        return response.toJSONString();
    }

    @Override
    public Collection<Category> searchCategories(String pQuery) {
        return aCategorySearch.queryCategories(pQuery);
    }

    @Override
    public Category getCategory(String pId) {
        return aDataStore.getCategory(pId);
    }

    @Override
    public List<RankExplanation> rankProducts(List<UserScoredAttribute> pUserScoredAttributes, String pCategoryID) {
        return aProductRanker.rankProducts(pUserScoredAttributes, aDataStore.getCategory(pCategoryID));
    }

    @Override
    public String sendCurrentFeatureList(String pUserFeatureList, String pCategoryId) {
        UserData userFMSpec = new Gson().fromJson(pUserFeatureList, UserData.class);
        List<UserScoredAttribute> userScoredFeaturesSpecs = new ArrayList<UserScoredAttribute>();
        for (UserFeaturesModel userFeature : userFMSpec.getUserFeatures()) {
            String tempId = userFeature.getId();
            ScoredAttribute sa = locateFeatureScoredAttribute(
                    aAttributeExtractor.getAttributesForCategory(pCategoryId), tempId);
            if (sa != null) {
                UserScoredAttribute usa = new UserScoredAttribute(sa, userFeature.getValue());
                userScoredFeaturesSpecs.add(usa);
            }

        }
        Collections.sort(userScoredFeaturesSpecs, UserScoredAttribute.SORT_BY_USER_SCORE);

        List<RankExplanation> rankedProducts = rankProducts(userScoredFeaturesSpecs, pCategoryId);

        ArrayList<ProductView> products = new ArrayList<ProductView>();
        for (RankExplanation productRankingExplanation : rankedProducts) {
            ArrayList<ExplanationView> explanation = new ArrayList<ExplanationView>();

            for (RankExplanationInstance rei : productRankingExplanation.getaRankList()) {
                TypedValue value = rei.getaAttributeValue();
                String attributeName = rei.getaAttribute().getAttributeName();
                explanation.add(new ExplanationView(attributeName, value, rei.getaAttributeRank(),
                        rei.getaAttribute().getUserScore()));
            }
            products.add(new ProductView(productRankingExplanation.getaProduct().getId(),
                    productRankingExplanation.getaProduct().getName(),
                    productRankingExplanation.getaProduct().getUrl(), explanation,
                    productRankingExplanation.getaProduct().getImage()));
        }

        String response = "";
        if (rankedProducts.size() > 0) {
            response = createExplainedProductsResponse(products);

        }

        return response;
    }

    /**
     * 
     * @param pProducts list of products to display.
     * @return Create JSON response object representing the products and their explanations.
     */
    private String createExplainedProductsResponse(ArrayList<ProductView> pProducts) {
        JsonArray jResponse = new JsonArray();

        for (ProductView productView : pProducts) {
            List<ExplanationView> expView = productView.getExplanation();

            JsonObject jProductObj = new JsonObject();
            JsonArray jExplanationArray = new JsonArray();

            jProductObj.addProperty("productID", productView.getId());
            jProductObj.addProperty("productName", productView.getName());
            jProductObj.addProperty("productURL", productView.getUrl());
            jProductObj.addProperty("productIMAGE", productView.getImage());

            for (ExplanationView e : expView) {
                JsonObject jExplanationElem = new JsonObject();

                TypedValue tValue = e.getValue();

                jExplanationElem.addProperty("name", e.getName());
                jExplanationElem.addProperty("productsNum", pProducts.size());
                jExplanationElem.addProperty("boolean", e.getIsBoolean());
                jExplanationElem.addProperty("rank", e.getValueRank());
                jExplanationElem.addProperty("userScore", e.getAttrScore());

                if (e.getValueRank() == -1) {
                    jExplanationElem.addProperty("isExplained", "-1");
                } else {
                    jExplanationElem.addProperty("isExplained", "1");

                    if (e.getIsBoolean()) {
                        if (tValue.getBoolean()) {
                            jExplanationElem.addProperty("boolValue", "True");

                        } else {
                            jExplanationElem.addProperty("boolValue", "False");
                        }
                    }
                }

                jExplanationArray.add(jExplanationElem);
            }
            jProductObj.add("explanation", jExplanationArray);
            jResponse.add(jProductObj);
        }
        return jResponse.toString();
    }

    /***
     * 
     * @param pUserFeatures list of scored attributes selected by the user.
     * @return list of sorted scored attributes according to attribute correlation.
     */
    public List<ScoredAttribute> sortFeatures(List<ScoredAttribute> pUserFeatures) {
        ScoredAttribute tmp = null;
        for (int i = 0; i < pUserFeatures.size(); i++) {
            for (int j = pUserFeatures.size() - 1; j >= i + 1; j--) {
                if (pUserFeatures.get(j).getCorrelation() > pUserFeatures.get(j - 1).getCorrelation()) {
                    tmp = pUserFeatures.get(j);
                    pUserFeatures.set(j, pUserFeatures.get(j - 1));
                    pUserFeatures.set(j - 1, tmp);
                }
            }
        }
        return pUserFeatures;
    }

    /***
     * 
     * @param pFeatureList list of all scored attributes.
     * @param pName name of the attribute to find.
     * @return scored attribute matching the parameter name
     */
    public ScoredAttribute locateFeatureScoredAttribute(List<ScoredAttribute> pFeatureList, String pID) {
        for (int i = 0; i < pFeatureList.size(); i++) {
            ScoredAttribute temp = pFeatureList.get(i);
            if (temp.getAttributeID().equals(pID)) {
                return temp;

            }
        }
        return null;
    }

    @Override
    public ArrayList<ProductView> searchRankedFeaturesProducts(String pCategoryId, Model pModel) {
        List<Product> prodSearch = aProductSort.returnTopProducts(pCategoryId);
        ArrayList<ProductView> products = new ArrayList<ProductView>();
        ArrayList<ExplanationView> emptyExplanation = new ArrayList<ExplanationView>();
        for (Product scoredProduct : prodSearch) {
            products.add(new ProductView(scoredProduct.getId(), scoredProduct.getName(), scoredProduct.getUrl(),
                    emptyExplanation, scoredProduct.getImage()));
        }
        return products;
    }

    @Override
    public ArrayList<FeatureView> createFeatureList(String pCategoryId) {
        ArrayList<FeatureView> specFeatures = new ArrayList<FeatureView>();
        List<ScoredAttribute> scoredAttr = aAttributeExtractor.getAttributesForCategory(pCategoryId);
        // Display top 10 scored attributes
        for (int i = 0; i < scoredAttr.size(); i++) {
            if (i > NUMBER_OF_FEATURES_TO_DISPLAY) {
                break;
            }
            FeatureView f = new FeatureView();
            f.setId(scoredAttr.get(i).getAttributeID());
            f.setName(scoredAttr.get(i).getAttributeName());
            f.setVisible(true);
            f.setDesc(scoredAttr.get(i).getAttributeDesc());

            if (scoredAttr.get(i).getAttributeID().equals("254")) {
                f.setScore(100);
            } else {
                f.setScore(0);
            }
            specFeatures.add(f);
        }
        return specFeatures;
    }

}