com.comcast.video.dawg.controller.park.ParkController.java Source code

Java tutorial

Introduction

Here is the source code for com.comcast.video.dawg.controller.park.ParkController.java

Source

/**
 * Copyright 2010 Comcast Cable Communications Management, LLC
 *
 * 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.comcast.video.dawg.controller.park;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.comcast.cereal.CerealException;
import com.comcast.cereal.CerealSettings;
import com.comcast.cereal.engines.JsonCerealEngine;
import com.comcast.video.dawg.common.MetaStb;
import com.comcast.video.dawg.common.PersistableDevice;
import com.comcast.video.dawg.common.ServerUtils;
import com.comcast.video.dawg.controller.house.DawgHouseConfiguration;
import com.comcast.video.dawg.controller.house.filter.Condition;
import com.comcast.video.dawg.controller.house.filter.Operator;
import com.comcast.video.dawg.controller.house.filter.SearchableField;
import com.comcast.video.dawg.controller.house.filter.TagCondition;
import com.comcast.video.dawg.service.park.ParkService;

@Controller
public class ParkController {

    /** JSON array separator. */
    private static final String SEPARATOR_JSON_ARRAY = ",";

    /** JSON array end element. */
    private static final String END_ELEMENT_JSON_ARRAY = "]";

    /** JSON array start element. */
    private static final String START_ELEMENT_JSON_ARRAY = "[";

    /** Empty JSON object. */
    private static final String EMPTY_JSON_OBJECT = "{}";

    /** Name of session attribute where advanced search conditions are saved. */
    private static final String SEARCH_CONDITIONS_SESSION_ATTRIBUTE_NAME = "searchConditions";

    /** Name of session attribute where latest advanced search condition saved. */
    private static final String LATEST_SEARCH_CONDITION_SESSION_ATTRIBUTE_NAME = "latestSearchCondition";

    /** Name of model attribute where advanced search conditions are saved. */
    private static final String SEARCH_CONDITIONS_MODEL_ATTRIBUTE_NAME = SEARCH_CONDITIONS_SESSION_ATTRIBUTE_NAME;

    /** Name of model attribute where latest advanced search condition saved. */
    private static final String LATEST_SEARCH_CONDITION_MODEL_ATTRIBUTE_NAME = LATEST_SEARCH_CONDITION_SESSION_ATTRIBUTE_NAME;

    Logger logger = Logger.getLogger(ParkController.class);

    @Autowired
    ParkService service;
    @Autowired
    ServerUtils serverUtils;

    @Autowired
    private DawgHouseConfiguration config;

    JsonCerealEngine engine = new JsonCerealEngine(false);

    @PostConstruct
    public void init() {
        CerealSettings settings = new CerealSettings();
        settings.setIncludeClassName(false);
        engine.setSettings(settings);
    }

    @RequestMapping({ "/", "index*" })
    public String index(Model model) throws CerealException {
        return "login";
    }

    @SuppressWarnings("unchecked")
    @RequestMapping("/{token}*")
    public String userFront(@PathVariable String token, @RequestParam(required = false) String tag,
            @RequestParam(required = false) String q, @RequestParam(required = false) Integer page,
            @RequestParam(required = false) Integer size, @RequestParam(required = false) Boolean asc,
            @RequestParam(required = false) String[] sort, Model model, HttpSession session)
            throws CerealException {

        StringBuilder builder = new StringBuilder();
        builder.append("Request=").append("token=").append(token).append(",q=").append(q).append(",tag=")
                .append(tag).append(",page=").append(page).append(",size=").append(size).append(",asc=").append(asc)
                .append(",sort=").append(sort);
        logger.info(builder.toString());
        if (isValid(token)) {
            token = clean(token);

            Map<String, Object>[] stbs = null;
            Map<String, Object>[] allDevices = null;
            Pageable pageable = null;
            if (null != sort) {
                if (0 == size) {
                    size = 100;
                }
                Direction direction = asc ? Direction.ASC : Direction.DESC;
                Sort sorting = new Sort(direction, sort);
                pageable = new PageRequest(page, size, sorting);
            }

            if (null != tag) {
                if (null != q) {
                    model.addAttribute("search", q);
                }
                stbs = service.findByCriteria(new TagCondition(tag, q).toCriteria(), pageable);
            } else if ((null != q) && (!q.trim().isEmpty())) {
                String[] keys = getKeys(q);
                stbs = service.findByKeys(keys, pageable);
                model.addAttribute("search", q);
            } else {

                Condition condition = (Condition) session.getAttribute("condition");
                if (condition != null) {
                    stbs = service.findByCriteria(condition.toCriteria(), pageable);
                    session.removeAttribute("condition");
                } else {
                    stbs = service.findAll(pageable);
                    model.addAttribute("search", "");
                    allDevices = stbs;
                }
            }

            Map<String, Object> requestParams = new HashMap<String, Object>();
            requestParams.put("tag", tag);
            requestParams.put("q", q);
            requestParams.put("page", page);
            requestParams.put("size", size);
            requestParams.put("asc", asc);
            requestParams.put("sort", sort);

            String requestParamsJson = engine.writeToString(requestParams, Map.class);
            model.addAttribute("requestParams", requestParamsJson);

            Map<String, Object> devices = new HashMap<String, Object>();
            Map<String, List<String>> deviceTags = new HashMap<String, List<String>>();
            Object tagData = null;
            boolean anyReserved = false;
            for (Map<String, Object> stb : stbs) {
                if (stb.containsKey(MetaStb.MACADDRESS)) {
                    String id = (String) stb.get(MetaStb.ID);
                    devices.put(id, stb);
                    tagData = stb.get(MetaStb.TAGS);
                    if (tagData != null && (tagData instanceof List)) {
                        deviceTags.put(id, (List<String>) tagData);
                    } else {
                        deviceTags.put(id, null);
                    }

                    String reserver = (String) stb.get(PersistableDevice.RESERVER);
                    if ((token != null) && token.equals(reserver)) {
                        anyReserved = true;
                    }
                }
            }
            String deviceData = engine.writeToString(devices, Map.class);

            /** Get all the tags from other devices */
            allDevices = allDevices == null ? service.findAll() : allDevices;
            Collection<String> otherTags = new HashSet<String>();
            for (Map<String, Object> device : allDevices) {
                String id = (String) device.get(MetaStb.ID);
                if (!deviceTags.containsKey(id)) {
                    tagData = device.get(MetaStb.TAGS);
                    if (tagData != null && (tagData instanceof List)) {
                        otherTags.addAll((List<String>) tagData);
                    }
                }
            }

            model.addAttribute(LATEST_SEARCH_CONDITION_MODEL_ATTRIBUTE_NAME,
                    returnAndRemoveLatestSearchCondition(session));
            model.addAttribute(SEARCH_CONDITIONS_MODEL_ATTRIBUTE_NAME, getSearchConditions(session));

            model.addAttribute("token", token);
            model.addAttribute("deviceData", deviceData);
            model.addAttribute("deviceTags", engine.writeToString(deviceTags));
            model.addAttribute("otherTags", engine.writeToString(new ArrayList<String>(otherTags)));
            model.addAttribute("data", devices.values());
            model.addAttribute("dawgShowUrl", config.getDawgShowUrl());
            model.addAttribute("dawgPoundUrl", config.getDawgPoundUrl());
            model.addAttribute("anyReserved", anyReserved);
            model.addAttribute("filterFields", SearchableField.values());
            model.addAttribute("operators", Operator.values());
            return "index";
        } else {
            /** User login token is invalid, so redirects to login page */
            return "login";
        }

    }

    @RequestMapping(value = "/filter/store", method = RequestMethod.POST)
    @ResponseBody
    public void storeFilter(@RequestBody String condition, HttpSession session)
            throws CerealException, ClassNotFoundException {
        /** Retaining the search condition in session to display the last advanced search executed by user. */
        session.setAttribute(LATEST_SEARCH_CONDITION_SESSION_ATTRIBUTE_NAME, condition);

        Condition c = engine.readFromString(condition, Condition.class);
        session.setAttribute("condition", c);
        validateAndUpdateSessionSearchConditions(c, session);
    }

    /**
     * Controller to remove the search condition stored in the history.
     *
     * @param condition
     *            advance search condition that need to be removed from the search condition list available in the
     *            session.
     * @param session
     *            User session object, where user previously executed search conditions are present.
     */
    @RequestMapping(value = "/filter/remove", method = RequestMethod.POST)
    @ResponseBody
    public void removeFilter(@RequestBody String condition, HttpSession session) {
        List<Condition> searchConditions = (List<Condition>) session
                .getAttribute(SEARCH_CONDITIONS_SESSION_ATTRIBUTE_NAME);
        if (!CollectionUtils.isEmpty(searchConditions) && null != condition) {
            try {
                Condition conditionToRemove = engine.readFromString(condition, Condition.class);
                searchConditions.remove(conditionToRemove);
            } catch (CerealException cerealException) {
                logger.error(String.format(
                        "Failed to convert search condition in JSON \"%s\" to object and remove it from list.",
                        condition), cerealException);
            }
        }
        session.setAttribute(SEARCH_CONDITIONS_SESSION_ATTRIBUTE_NAME, searchConditions);
    }

    /**
     * Method add the new search condition to the advance search list present in the session. Before adding to the list
     * it removes any duplicate entry present in the list.
     *
     * @param condition
     *            advance search condition carried out by user.
     * @param session
     *            User session object where user previously executed search conditions are present.
     */
    private void validateAndUpdateSessionSearchConditions(Condition condition, HttpSession session) {
        /** Add the new advanced search condition to previously executed search list. */
        List<Condition> searchConditions = (List<Condition>) session
                .getAttribute(SEARCH_CONDITIONS_SESSION_ATTRIBUTE_NAME);
        if (null != searchConditions) {
            // If the user carried out a similar advance search earlier, it need to be removed from the previous
            // stored list.
            searchConditions.remove(condition);
        } else {
            searchConditions = new CopyOnWriteArrayList<Condition>();
        }
        searchConditions.add(condition);
        session.setAttribute(SEARCH_CONDITIONS_SESSION_ATTRIBUTE_NAME, searchConditions);
    }

    /**
     * Provides the list of previously executed advanced search condition in a JSON array.
     *
     * @param session
     *            User session object where user previously executed search condition are present.
     * @return JSON array string of search carried out by user, blank JSON array string if no search where executed by
     *         the user.
     */
    private String getSearchConditions(HttpSession session) {
        String searchCondtions = new String(START_ELEMENT_JSON_ARRAY + END_ELEMENT_JSON_ARRAY);
        List<Condition> searchConditionList = (List<Condition>) session
                .getAttribute(SEARCH_CONDITIONS_SESSION_ATTRIBUTE_NAME);
        if (!CollectionUtils.isEmpty(searchConditionList)) {
            // --class representation is required in JSON output, so not using the class level JSON engine.
            JsonCerealEngine jsonEngine = new JsonCerealEngine(true);
            jsonEngine.getSettings().setUseObjectReferences(false);
            try {
                searchCondtions = jsonEngine.writeToString(searchConditionList, List.class);
            } catch (CerealException cerealException) {
                logger.error("Failed to convert the search condition to JSON.", cerealException);
            }
        }
        return searchCondtions;
    }

    /**
     * Provides the user latest executed search JSON string extracted from the user session object. After processing the
     * request it removes the latest search condition from session
     *
     * @param session
     *            User session object where last user executed advance search condition is present.
     * @return Latest JSON advanced search condition executed by user, blank JSON object if no latest advanced search
     *         executed by user.
     */
    private String returnAndRemoveLatestSearchCondition(HttpSession session) {
        String searchCondition = EMPTY_JSON_OBJECT;
        Object sessionSearchCondtion = session.getAttribute(LATEST_SEARCH_CONDITION_SESSION_ATTRIBUTE_NAME);
        if (null != sessionSearchCondtion) {
            searchCondition = (String) sessionSearchCondtion;
            session.removeAttribute(LATEST_SEARCH_CONDITION_SESSION_ATTRIBUTE_NAME);
        }
        return searchCondition;
    }

    private String[] getKeys(String query) {
        query = query.toLowerCase();
        logger.info("keys=" + (Arrays.asList(query.split(" "))));
        return query.split(" ");
    }

    protected String clean(String string) {
        return serverUtils.clean(string);
    }

    protected boolean isValid(String string) {
        return serverUtils.isValid(string);
    }
}