org.egov.infra.gis.service.GeoLocationService.java Source code

Java tutorial

Introduction

Here is the source code for org.egov.infra.gis.service.GeoLocationService.java

Source

/*
 *    eGov  SmartCity eGovernance suite aims to improve the internal efficiency,transparency,
 *    accountability and the service delivery of the government  organizations.
 *
 *     Copyright (C) 2017  eGovernments Foundation
 *
 *     The updated version of eGov suite of products as by eGovernments Foundation
 *     is available at http://www.egovernments.org
 *
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with this program. If not, see http://www.gnu.org/licenses/ or
 *     http://www.gnu.org/licenses/gpl.html .
 *
 *     In addition to the terms of the GPL license to be adhered to in using this
 *     program, the following additional terms are to be complied with:
 *
 *         1) All versions of this program, verbatim or modified must carry this
 *            Legal Notice.
 *            Further, all user interfaces, including but not limited to citizen facing interfaces,
 *            Urban Local Bodies interfaces, dashboards, mobile applications, of the program and any
 *            derived works should carry eGovernments Foundation logo on the top right corner.
 *
 *            For the logo, please refer http://egovernments.org/html/logo/egov_logo.png.
 *            For any further queries on attribution, including queries on brand guidelines,
 *            please contact contact@egovernments.org
 *
 *         2) Any misrepresentation of the origin of the material is prohibited. It
 *            is required that all modified versions of this material be marked in
 *            reasonable ways as different from the original version.
 *
 *         3) This license does not grant any rights to any user of the program
 *            with regards to rights under trademark law for use of the trade names
 *            or trademarks of eGovernments Foundation.
 *
 *   In case of any queries, you can reach eGovernments Foundation at contact@egovernments.org.
 *
 */

package org.egov.infra.gis.service;

import org.apache.commons.lang.StringUtils;
import org.egov.infra.exception.ApplicationRuntimeException;
import org.egov.infra.gis.model.GeoKmlInfo;
import org.egov.infra.gis.model.GeoLocation;
import org.egov.infra.validation.exception.ValidationError;
import org.egov.infra.validation.exception.ValidationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;

public class GeoLocationService {

    private static final Logger LOGGER = LoggerFactory.getLogger(GeoLocationService.class);

    /**
     * 
     * @param geoLocation - contains the latitude and longitude , and the info window text to be show on the click event of the marker.  
     * @return - the html code to display the static text in the marker info window.
     */
    public static String getMarkerDesc(GeoLocation geoLocation) {

        StringBuffer markerDesc = new StringBuffer(1000);
        markerDesc
                .append(null != geoLocation.getInfo1() ? "<tr><td><b>"
                        + geoLocation.getInfo1().substring(0, geoLocation.getInfo1().indexOf("=")) + "</b></td><td>"
                        + geoLocation.getInfo1().substring(geoLocation.getInfo1().indexOf("=") + 1) + "</td></tr>"
                        : "")
                .append(null != geoLocation.getInfo2() ? "<tr><td><b>"
                        + geoLocation.getInfo2().substring(0, geoLocation.getInfo2().indexOf("=")) + "</b></td><td>"
                        + geoLocation.getInfo2().substring(geoLocation.getInfo2().indexOf("=") + 1) + "</td></tr>"
                        : "")
                .append(null != geoLocation.getInfo3() ? "<tr><td><b>"
                        + geoLocation.getInfo3().substring(0, geoLocation.getInfo3().indexOf("=")) + "</b></td><td>"
                        + geoLocation.getInfo3().substring(geoLocation.getInfo3().indexOf("=") + 1) + "</td></tr>"
                        : "")
                .append(null != geoLocation.getInfo1() ? "<tr><td><b>"
                        + geoLocation.getInfo4().substring(0, geoLocation.getInfo4().indexOf("=")) + "</b></td><td>"
                        + geoLocation.getInfo4().substring(geoLocation.getInfo4().indexOf("=") + 1) + "</td></tr>"
                        : "");
        return markerDesc.toString();

    }

    /**
     * 
     * @param geoLoc - the marker option object , which is going to be passed to the marker constructor 
     * @return - the marker option javascript object.
     */

    public static String getMarkerOption(GeoLocation geoLoc) {
        StringBuffer markerOption = new StringBuffer(1000);
        markerOption.append("{").append("position: new google.maps.LatLng('")
                .append(geoLoc.getGeoLatLong().getLatitude()).append("','")
                .append(geoLoc.getGeoLatLong().getLongitude()).append("'), map: map");
        Map<String, Object> markerOptData = geoLoc.getMarkerOptionData();
        if (null != markerOptData && markerOptData.size() > 0) {
            for (Map.Entry<String, Object> entry : markerOptData.entrySet()) {
                String value = entry.getValue().toString();
                if (entry.getKey().equalsIgnoreCase(GeoLocationConstants.MARKEROPTION_ICON)) {
                    value = "http://www.google.com/mapfiles/ms/icons/" + value + "-dot.png";
                }
                markerOption.append(",").append(entry.getKey()).append(":'").append(value).append("'");
            }
        }

        markerOption.append("};");
        return markerOption.toString();
    }

    /**
     * puts the kml data model into the map and returns the random key which is used to fetch the exact kmldatamodel from the cache.
     * @param kmlDataMap - Kml data model map to store into the jboss cache, for the purpose generating the KML file by passing the kml file
     * and the data model map to the freemarker.
     * @return
     */
    private static String putKmlDataToCache(GeoKmlInfo geoKmlInfo) {

        Map<String, Object> cacheDataModelMap = new HashMap<String, Object>();
        String kmlDataModelKey = UUID.randomUUID().toString().substring(0, 10);
        cacheDataModelMap.put(kmlDataModelKey, geoKmlInfo);
        /*try {
           //TODO CACHE
           //che.put(GeoLocationConstants.KML_DATA_JBOSS_CACHE_NODE,cacheDataModelMap);
        } catch (CacheException e) {
           LOGGER.error(e.getMessage());
        }*/
        return kmlDataModelKey;

    }

    /**
     * 
     * @param kmlDataModelKey - 
     * @return 
     */
    public static GeoKmlInfo getKmlDataFromCache(String kmlDataModelKey) {
        GeoKmlInfo geoKmlInfo = null;
        //TODO CACHE
        /*try {
           geoKmlInfo =  (GeoKmlInfo) cache.get(GeoLocationConstants.KML_DATA_JBOSS_CACHE_NODE,kmlDataModelKey);
        } catch (CacheException e) {
           LOGGER.error(e.getMessage());
        }*/
        if (null == geoKmlInfo) {
            LOGGER.error("Could not able to retrive kml data  from cache for the key " + kmlDataModelKey);
            throw new ApplicationRuntimeException(
                    "Could not able to retrive kml data  from cache for the key " + kmlDataModelKey);
        }
        return geoKmlInfo;
    }

    /**
     * 
     * @param wardWiseData Map<String, Integer>- Map having the key as the ward number and value as the no of complaints/properties/assets
     *    in that ward. e.g [<Ward Number>,<no Of Complaints/assets/properties> ]
     * 
     * @param colorCodes Map<Integer,String> - Map having colour codes , the key as the the colour priority and value as the colour 
     * code in RGB format. e.g - key = 1 , means the associated colour to represent the ward having  no of complaints/assets/properties
     * that falls in highest range , key = 2 means associated colour to represent ward having  no of complaints/assets/properties
     * that falls in the 2nd highest range and so on.
     * example :  (1, "FF0000");
     *           (2, "8968CD");
     *            (3, "FFA500");
     *            (4, "4169E1");
     *            (5, "008B00");
     */

    public static void setKmlDataToCacheAndRequest(Map<String, BigDecimal> wardWiseData,
            Map<Integer, String> colorCodes, String kmlPath, HttpServletRequest request) {

        LOGGER.debug("GeoLocationService | setKmlDataToCacheAndRequest | Start");

        int totalNoOfColors = colorCodes.size();
        BigDecimal wardDataMinAmount = Collections.min(wardWiseData.values()).setScale(0, BigDecimal.ROUND_HALF_UP); // to hold the minimum amount in all the wards.
        BigDecimal wardDataMaxAmount = Collections.max(wardWiseData.values()).setScale(0, BigDecimal.ROUND_HALF_UP); // to hold the maximum amount in all the wards.
        if ((wardDataMaxAmount.subtract(wardDataMinAmount)).compareTo(BigDecimal.valueOf(totalNoOfColors)) == -1) {
            throw new ValidationException(Arrays.asList(new ValidationError("colorrange",
                    "no of colors supplied is more than the range of data " + "in the wards")));
        }

        BigDecimal rangeSize = getRangeSize(wardDataMinAmount, wardDataMaxAmount, totalNoOfColors);

        GeoKmlInfo geoKmlInfo = new GeoKmlInfo();
        Map<String, String> wardWiseKmlColorStyle = new HashMap<String, String>();

        for (Map.Entry<String, BigDecimal> entry : wardWiseData.entrySet()) {
            wardWiseKmlColorStyle.put("style" + entry.getKey(),
                    getStyleColorName(entry.getValue(), wardDataMinAmount, totalNoOfColors, rangeSize));
        }

        geoKmlInfo.setWardWiseColor(wardWiseKmlColorStyle);
        geoKmlInfo.setColorCodes(convertToKmlColor(colorCodes));

        request.setAttribute(GeoLocationConstants.KML_DATA_MODEL_JBOSS_CACHE_KEY_NAME,
                putKmlDataToCache(geoKmlInfo));
        request.setAttribute(GeoLocationConstants.COLOR_CODE_AND_RANGE_MAP_NAME,
                getColorRange(wardDataMinAmount, wardDataMaxAmount, rangeSize, colorCodes));
        if (null != kmlPath && StringUtils.isNotEmpty(kmlPath)) {
            request.setAttribute(GeoLocationConstants.KML_URL_PATH_REQ_ATTR_NAME, kmlPath);
        }

        LOGGER.debug("GeoLocationService | setKmlDataToCacheAndRequest | End");

    }

    private static Map<String, String> convertToKmlColor(Map<Integer, String> colorMap) {

        Map<String, String> kmlColorConvertedMap = new HashMap<String, String>();

        for (Map.Entry<Integer, String> entry : colorMap.entrySet()) {
            String color = entry.getValue();
            color = "FF" + color.substring(4, 6) + color.substring(2, 4) + color.substring(0, 2); // FF appended for the opacity level.
            kmlColorConvertedMap.put(GeoLocationConstants.KML_STYLE_COLOR + entry.getKey(), color);
        }

        return kmlColorConvertedMap;
    }

    /**
     * 
     * @param TotalNos e.g = 50
     * @param colorMap - the different colours to be shown in the kml.
     * @return = [0-10,11-20,21-30,31-40,41-50]
     */
    private static Map<String, String> getColorRange(BigDecimal wardDataMinAmount, BigDecimal wardDataMaxAmount,
            BigDecimal rangeSize, Map<Integer, String> colorCodes) {
        int totalNoOfColors = colorCodes.size();

        Map<String, String> colorRangeMap = new LinkedHashMap<String, String>(); // map to hold the colour code and the range .

        BigDecimal rangeStartVal = wardDataMinAmount;
        BigDecimal rangeEndVal = wardDataMinAmount;
        for (int i = 0; i < totalNoOfColors; i++) {

            if (totalNoOfColors != i + 1) {
                rangeEndVal = (rangeStartVal.add(rangeSize)).subtract(BigDecimal.ONE);
            } else {
                rangeEndVal = wardDataMaxAmount;
            }

            String colorRange = rangeStartVal + " - " + rangeEndVal;
            colorRangeMap.put(colorCodes.get((totalNoOfColors - i)), colorRange);
            BigDecimal nextRangeStartVal = rangeEndVal.add(BigDecimal.ONE);
            rangeStartVal = nextRangeStartVal;

        }
        return colorRangeMap;
    }

    private static String getStyleColorName(BigDecimal wardWiseNos, BigDecimal wardDataMinAmount,
            Integer totalNoOfColors, BigDecimal rangeSize) {

        return "#color" + (BigDecimal.valueOf(totalNoOfColors)
                .subtract((wardWiseNos.subtract(wardDataMinAmount).subtract(BigDecimal.ONE)).divide(rangeSize, 0,
                        BigDecimal.ROUND_DOWN)));

    }

    private static BigDecimal getRangeSize(BigDecimal wardDataMinAmount, BigDecimal wardDataMaxAmount,
            int totalNoOfColors) {

        BigDecimal rangeSize = (wardDataMaxAmount.subtract(wardDataMinAmount))
                .divide(BigDecimal.valueOf(totalNoOfColors), BigDecimal.ROUND_HALF_UP);
        return rangeSize;
    }

}