/* * eGov suite of products aim to improve the internal efficiency,transparency, * accountability and the service delivery of the government organizations. * * Copyright (C) <2015> 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. * * 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; } }