/*
* Copyright (C) 2012 Stichting Akvo (Akvo Foundation)
*
* This file is part of Akvo FLOW.
*
* Akvo FLOW is free software: you can redistribute it and modify it under the terms of
* the GNU Affero General Public License (AGPL) as published by the Free Software Foundation,
* either version 3 of the License or any later version.
*
* Akvo FLOW 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 Affero General Public License included below for more details.
*
* The full license text can also be seen at <http://www.gnu.org/licenses/agpl.html>.
*/
package org.waterforpeople.mapping.app.web.rest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
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 org.waterforpeople.mapping.app.web.rest.dto.PlacemarkDto;
import org.waterforpeople.mapping.app.web.rest.security.AppRole;
import com.gallatinsystems.surveyal.dao.SurveyedLocaleClusterDao;
import com.gallatinsystems.surveyal.dao.SurveyedLocaleDao;
import com.gallatinsystems.surveyal.domain.SurveyedLocale;
import com.gallatinsystems.surveyal.domain.SurveyedLocaleCluster;
@Controller
@RequestMapping("/placemarks")
public class PlacemarkRestService {
final int LIMIT_PLACEMARK_POINTS = 2000;
private static final Logger log = Logger
.getLogger(PlacemarkRestService.class.getName());
@Inject
SurveyedLocaleDao localeDao;
@Inject
SurveyedLocaleClusterDao slcDao;
@RequestMapping(method = RequestMethod.GET, value = "")
@ResponseBody
public Map<String, Object> listPlaceMarks(
@RequestParam(value = "bbString", defaultValue = "") String boundingBoxString,
@RequestParam(value = "gcLevel", defaultValue = "") Integer gcLevel) {
// assume we are on the public map
Boolean allPlacemarks = false;
log.log(Level.FINE, "received request for: " + boundingBoxString + ", " + gcLevel);
List<String> geocells = Arrays.asList(boundingBoxString.split(","));
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null) {
Collection<? extends GrantedAuthority> auths = authentication.getAuthorities();
if (auths.contains(AppRole.USER) || auths.contains(AppRole.ADMIN)
|| auths.contains(AppRole.SUPER_ADMIN)) {
allPlacemarks = true;
}
}
return getPlacemarksReponse(geocells, gcLevel, allPlacemarks);
}
@RequestMapping(method = RequestMethod.GET, value = "/{id}")
@ResponseBody
public Map<String, Object> placeMarkDetails(@PathVariable("id") Long id) {
return getPlacemarkResponseById(id);
}
private Map<String, Object> getPlacemarksReponse(List<String> geocells, Integer gcLevel,
Boolean allPlacemarks) {
final Map<String, Object> response = new HashMap<String, Object>();
final List<PlacemarkDto> result = new ArrayList<PlacemarkDto>();
final List<SurveyedLocaleCluster> slcList;
if (gcLevel > 0) {
// get clusters on the basis of the geocells list received from the dashboard,
// and the required level of clustering. The geocells list form the viewport,
// and in this viewport we still have to determine the right cluster level.
// The dashboard is responsible for asking for a level that makes sense.
if (allPlacemarks) {
slcList = slcDao.listLocaleClustersByGeocell(geocells, gcLevel);
} else {
slcList = slcDao.listPublicLocaleClustersByGeocell(geocells, gcLevel);
}
if (slcList.size() > 0) {
for (SurveyedLocaleCluster slc : slcList) {
result.add(marshallClusterDomainToDto(slc));
}
}
} else {
final List<SurveyedLocale> slList = new ArrayList<SurveyedLocale>();
// get surveyedLocales
if (allPlacemarks) {
slList.addAll(localeDao.listLocalesByGeocell(geocells, LIMIT_PLACEMARK_POINTS));
} else {
// exclude Household data
slList.addAll(localeDao
.listPublicLocalesByGeocell(geocells, LIMIT_PLACEMARK_POINTS));
}
if (slList.size() > 0) {
for (SurveyedLocale sl : slList) {
result.add(marshallDomainToDto(sl));
}
}
}
response.put("placemarks", result);
return response;
}
private Map<String, Object> getPlacemarkResponseById(Long id) {
final Map<String, Object> response = new HashMap<String, Object>();
final SurveyedLocale sl = localeDao.getById(id);
if (sl == null) {
throw new HttpMessageNotReadableException("ID not found");
}
response.put("placemark", marshallDomainToDto(sl));
return response;
}
private PlacemarkDto marshallDomainToDto(SurveyedLocale sl) {
final PlacemarkDto dto = new PlacemarkDto();
dto.setLatitude(sl.getLatitude());
dto.setLongitude(sl.getLongitude());
dto.setCount(1);
dto.setDetailsId(sl.getKey().getId());
dto.setLevel(0);
dto.setSurveyId(sl.getCreationSurveyId());
dto.setCollectionDate(sl.getLastSurveyedDate());
// make even to avoid clash with cluster keyIds in client cache
dto.setKeyId(sl.getKey().getId() * 2);
return dto;
}
private PlacemarkDto marshallClusterDomainToDto(SurveyedLocaleCluster slc) {
final PlacemarkDto dto = new PlacemarkDto();
dto.setLatitude(slc.getLatCenter());
dto.setLongitude(slc.getLonCenter());
dto.setCount(slc.getCount());
dto.setLevel(slc.getLevel());
// make odd to avoid clash with cluster keyIds in client cache
dto.setKeyId(slc.getKey().getId() * 2 + 1);
if (slc.getCount() == 1) {
dto.setDetailsId(slc.getFirstSurveyedLocaleId());
dto.setCollectionDate(slc.getFirstCollectionDate());
}
return dto;
}
}