/* ==================================================================
* LocationLookupController.java - Feb 20, 2011 7:54:21 PM
*
* Copyright 2007-2011 SolarNetwork.net Dev Team
*
* 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 2 of
* the License, or (at your option) 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
* ==================================================================
*/
package net.solarnetwork.central.in.web;
import java.util.List;
import javax.validation.Valid;
import net.solarnetwork.central.dao.SolarNodeDao;
import net.solarnetwork.central.domain.EntityMatch;
import net.solarnetwork.central.domain.SourceLocationMatch;
import net.solarnetwork.central.in.biz.DataCollectorBiz;
import net.solarnetwork.central.support.SourceLocationFilter;
import net.solarnetwork.web.domain.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
/**
* Web access to PriceLocation data.
*
* @author matt
* @version 1.2
*/
@Controller
public class LocationLookupController {
/** The default value for the {@code viewName} property. */
public static final String DEFAULT_VIEW_NAME = "xml";
/** The model key for the {@code PriceLocation} result. */
public static final String MODEL_KEY_RESULT = "result";
private DataCollectorBiz dataCollectorBiz;
private String viewName = DEFAULT_VIEW_NAME;
private final Logger log = LoggerFactory.getLogger(getClass());
/**
* Default constructor.
*/
public LocationLookupController() {
super();
}
/**
* Constructor.
*
* @param dataCollectorBiz
* the {@link DataCollectorBiz} to use
* @param solarNodeDao
* the {@link SolarNodeDao} to use
*/
@Autowired
public LocationLookupController(DataCollectorBiz dataCollectorBiz) {
setDataCollectorBiz(dataCollectorBiz);
}
private class CriteriaValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return true;
}
@Override
public void validate(Object target, Errors errors) {
if ( target instanceof SourceLocationFilter ) {
boolean sourceRequired = true;
SourceLocationFilter filter = (SourceLocationFilter) target;
if ( filter.getId() != null
|| (target instanceof GenericSourceLocationFilter && ((GenericSourceLocationFilter) target)
.getType() == GenericSourceLocationFilter.LocationType.Basic) ) {
sourceRequired = false;
}
if ( sourceRequired ) {
if ( !StringUtils.hasText(filter.getSourceName()) ) {
errors.rejectValue("sourceName", "error.field.required",
new Object[] { "sourceName" }, "Field is required.");
}
if ( !StringUtils.hasText(filter.getLocationName()) ) {
errors.rejectValue("locationName", "error.field.required",
new Object[] { "locationName" }, "Field is required.");
}
}
}
}
}
/**
* Web binder initialization.
*
* @param binder
* the binder to initialize
*/
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setValidator(new CriteriaValidator());
binder.setIgnoreInvalidFields(true);
}
/**
* Handle an {@link RuntimeException}.
*
* @param e
* the exception
* @param response
* the response
* @return an error response object
*/
@ExceptionHandler({ BindException.class, RuntimeException.class })
public ModelAndView handleRuntimeException(Exception e) {
log.error("BindException in {} controller", getClass().getSimpleName(), e);
ModelAndView mv = new ModelAndView(getViewName(), MODEL_KEY_RESULT, new Response<Object>(false,
null, e.getMessage(), null));
return mv;
}
/**
* Query for a WeatherLocation.
*
* @param criteria
* the search criteria
* @param model
* the model
* @return the result view name
*/
@RequestMapping(method = RequestMethod.GET, value = { "/weatherLocationLookup.do",
"/u/weatherLocationLookup.do" })
public String findWeatherLocation(@Valid SourceLocationFilter criteria, Model model) {
List<SourceLocationMatch> matches = getDataCollectorBiz().findWeatherLocations(criteria);
if ( matches != null ) {
model.asMap().clear();
model.addAttribute(MODEL_KEY_RESULT, matches);
}
return getViewName();
}
/**
* Query for a PriceLocation.
*
* @param criteria
* the search criteria
* @param model
* the model
* @param criteriaModelKey
* the model key the criteria is stored on
* @return the result model name
*/
@RequestMapping(method = RequestMethod.GET, value = { "/priceLocationLookup.do",
"/u/priceLocationLookup.do" })
public String findPriceLocation(@Valid SourceLocationFilter criteria, Model model) {
List<SourceLocationMatch> matches = getDataCollectorBiz().findPriceLocations(criteria);
if ( matches != null && matches.size() > 0 ) {
model.asMap().clear();
model.addAttribute(MODEL_KEY_RESULT, matches.get(0));
}
return getViewName();
}
/**
* Query for a PriceLocation.
*
* @param criteria
* the search criteria
* @param model
* the model
* @return the result view name
*/
@RequestMapping(method = RequestMethod.GET, value = { "/priceLocationSearch.*",
"/u/priceLocationSearch.*" })
public String searchForPriceLocation(@Valid SourceLocationFilter criteria, Model model) {
List<SourceLocationMatch> matches = getDataCollectorBiz().findPriceLocations(criteria);
if ( matches != null && matches.size() > 0 ) {
model.asMap().clear();
model.addAttribute(MODEL_KEY_RESULT, matches.get(0));
}
return getViewName();
}
/**
* Query for any supported location type.
*
* @param criteria
* the search criteria
* @param model
* the model
* @return the result view name
*/
@RequestMapping(method = RequestMethod.GET, value = { "/locationSearch.*", "/u/locationSearch.*" })
public String searchForLocations(@Valid GenericSourceLocationFilter criteria, Model model) {
List<? extends EntityMatch> matches;
switch (criteria.getType()) {
case Price:
matches = getDataCollectorBiz().findPriceLocations(criteria);
break;
case Weather:
matches = getDataCollectorBiz().findWeatherLocations(criteria);
break;
default:
matches = getDataCollectorBiz().findLocations(criteria.getLocation());
break;
}
if ( matches != null && matches.size() > 0 ) {
model.asMap().clear();
model.addAttribute(MODEL_KEY_RESULT, matches);
}
return getViewName();
}
public DataCollectorBiz getDataCollectorBiz() {
return dataCollectorBiz;
}
public void setDataCollectorBiz(DataCollectorBiz dataCollectorBiz) {
this.dataCollectorBiz = dataCollectorBiz;
}
public String getViewName() {
return viewName;
}
public void setViewName(String viewName) {
this.viewName = viewName;
}
}