diff --git a/src/main/java/no/nibio/vips/logic/controller/servlet/ForecastConfigurationController.java b/src/main/java/no/nibio/vips/logic/controller/servlet/ForecastConfigurationController.java index c004507e7563cc12a0de65263f707bc290a10671..5da379dda13007cbbe8ac20e14e38113142058c4 100755 --- a/src/main/java/no/nibio/vips/logic/controller/servlet/ForecastConfigurationController.java +++ b/src/main/java/no/nibio/vips/logic/controller/servlet/ForecastConfigurationController.java @@ -1,24 +1,21 @@ /* * Copyright (c) 2014 NIBIO <http://www.nibio.no/>. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General + * Public License as published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. + * 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 Affero General Public License for more + * details. * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. + * You should have received a copy of the GNU Affero General Public License along with this program. If not, see + * <https://www.gnu.org/licenses/>. * */ package no.nibio.vips.logic.controller.servlet; -import com.ibm.icu.util.Calendar; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -35,15 +32,18 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; - +import com.ibm.icu.util.Calendar; import no.nibio.vips.logic.controller.session.ForecastBean; import no.nibio.vips.logic.controller.session.OrganismBean; import no.nibio.vips.logic.controller.session.PointOfInterestBean; import no.nibio.vips.logic.controller.session.UserBean; -import no.nibio.vips.logic.entity.*; +import no.nibio.vips.logic.entity.ForecastConfiguration; +import no.nibio.vips.logic.entity.ModelInformation; +import no.nibio.vips.logic.entity.Organization; +import no.nibio.vips.logic.entity.VipsLogicRole; +import no.nibio.vips.logic.entity.VipsLogicUser; import no.nibio.vips.logic.i18n.SessionLocaleUtil; import no.nibio.vips.logic.util.Globals; import no.nibio.vips.logic.util.SystemTime; @@ -56,6 +56,7 @@ import no.nibio.web.forms.FormValidator; /** * Handles form configuration actions + * * @copyright 2020-2022 <a href="http://www.nibio.no/">NIBIO</a> * @author Tor-Einar Skog <tor-einar.skog@nibio.no> */ @@ -63,15 +64,15 @@ public class ForecastConfigurationController extends HttpServlet { private static final Logger LOGGER = LoggerFactory.getLogger(ForecastConfigurationController.class); - @PersistenceContext(unitName="VIPSLogic-PU") + @PersistenceContext(unitName = "VIPSLogic-PU") EntityManager em; - + @EJB ForecastBean forecastBean; - + @EJB UserBean userBean; - + @EJB OrganismBean organismBean; @@ -79,8 +80,7 @@ public class ForecastConfigurationController extends HttpServlet { PointOfInterestBean pointOfInterestBean; /** - * Processes requests for both HTTP <code>GET</code> and <code>POST</code> - * methods. + * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods. * * @param request servlet request * @param response servlet response @@ -90,89 +90,79 @@ public class ForecastConfigurationController extends HttpServlet { protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); - + String action = request.getParameter("action"); VipsLogicUser user = (VipsLogicUser) request.getSession().getAttribute("user"); - + // Default: View list of forecast configurations // for SUPERUSERS and ORGANIZATION ADMINS - if(action == null) - { + if (action == null) { Map<String, ModelInformation> modelInformationMap = forecastBean.getIndexedBatchableModelInformation(); - if(userBean.authorizeUser(user, VipsLogicRole.ORGANIZATION_ADMINISTRATOR, VipsLogicRole.SUPERUSER)) - { + if (userBean.authorizeUser(user, VipsLogicRole.ORGANIZATION_ADMINISTRATOR, VipsLogicRole.SUPERUSER)) { // Check filtering conditions List<String> selectedModelIds; - try - { + try { selectedModelIds = Arrays.asList(request.getParameterValues("modelId")); - } - catch(NullPointerException ex) - { + } catch (NullPointerException ex) { selectedModelIds = new ArrayList(modelInformationMap.keySet()); } - + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); - Date from,to; - try - { + Date from, to; + try { from = format.parse(request.getParameter("from")); to = format.parse(request.getParameter("to")); - } - catch(NullPointerException | ParseException ex) - { + } catch (NullPointerException | ParseException ex) { to = SystemTime.getSystemTime(); Calendar cal = Calendar.getInstance(); cal.setTime(to); cal.add(Calendar.MONTH, -2); from = cal.getTime(); } - + List<ForecastConfiguration> forecasts; - - if(user.isSuperUser()) - { + + if (user.isSuperUser()) { // Filtering of organizations List<Organization> organizations = userBean.getOrganizations(); List<Integer> selectedOrganizationIds; - try - { - selectedOrganizationIds = Arrays.asList(ArrayUtil.stringArrayToIntegerArray(request.getParameterValues("organizationId"))); + try { + selectedOrganizationIds = Arrays.asList( + ArrayUtil.stringArrayToIntegerArray(request.getParameterValues("organizationId"))); } // No filter set -> select all organizations (default) - catch(NullPointerException ex) - { + catch (NullPointerException ex) { selectedOrganizationIds = new ArrayList<>(); - for(Organization o:organizations) - { + for (Organization o : organizations) { selectedOrganizationIds.add(o.getOrganizationId()); } } - forecasts = forecastBean.getForecastConfigurations(selectedOrganizationIds, selectedModelIds, from, to); - + forecasts = + forecastBean.getForecastConfigurations(selectedOrganizationIds, selectedModelIds, from, to); + request.setAttribute("organizations", organizations); request.setAttribute("selectedOrganizationIds", selectedOrganizationIds); - + request.setAttribute("allUsers", userBean.getAllUsers()); // If super user requests private forecasts for a user - try - { + try { Integer otherUserId = Integer.valueOf(request.getParameter("otherUserId")); - List<ForecastConfiguration> privateForecastConfigurationsForOtherUser = forecastBean.getPrivateForecastConfigurationsForUser(otherUserId); - request.setAttribute("privateForecastConfigurationsForOtherUser", privateForecastConfigurationsForOtherUser); + List<ForecastConfiguration> privateForecastConfigurationsForOtherUser = + forecastBean.getPrivateForecastConfigurationsForUser(otherUserId); + request.setAttribute("privateForecastConfigurationsForOtherUser", + privateForecastConfigurationsForOtherUser); request.setAttribute("otherUserId", otherUserId); + } catch (NumberFormatException nfe) { } - catch(NumberFormatException nfe) {} - } - else - { - forecasts = forecastBean.getForecastConfigurations(user.getOrganizationId(), selectedModelIds, from, to); + } else { + forecasts = forecastBean.getForecastConfigurations(user.getOrganizationId(), selectedModelIds, from, + to); } Collections.sort(forecasts); request.setAttribute("currentLanguage", SessionLocaleUtil.getCurrentLocale(request).getLanguage()); request.setAttribute("forecastConfigurations", forecasts); - + List<ForecastConfiguration> privateForecasts; privateForecasts = forecastBean.getPrivateForecastConfigurationsForUser(user.getUserId()); request.setAttribute("privateForecastConfigurations", privateForecasts); @@ -183,9 +173,7 @@ public class ForecastConfigurationController extends HttpServlet { // If this is a redirect from a controller, with a message to be passed on request.setAttribute("messageKey", request.getParameter("messageKey")); request.getRequestDispatcher("/forecastConfigurationList.ftl").forward(request, response); - } - else - { + } else { List<ForecastConfiguration> privateForecasts; privateForecasts = forecastBean.getPrivateForecastConfigurationsForUser(user.getUserId()); request.setAttribute("privateForecastConfigurations", privateForecasts); @@ -193,244 +181,264 @@ public class ForecastConfigurationController extends HttpServlet { request.setAttribute("messageKey", request.getParameter("messageKey")); request.getRequestDispatcher("/forecastConfigurationList.ftl").forward(request, response); } - + } - + // View and edit a forecast configuration - else if(action.equals("viewForecastConfiguration")) - { - if(userBean.authorizeUser(user, VipsLogicRole.ORGANIZATION_ADMINISTRATOR, VipsLogicRole.SUPERUSER)) - { - try - { + else if (action.equals("viewForecastConfiguration")) { + if (userBean.authorizeUser(user, VipsLogicRole.ORGANIZATION_ADMINISTRATOR, VipsLogicRole.SUPERUSER)) { + try { Long forecastConfigurationId = Long.valueOf(request.getParameter("forecastConfigurationId")); - ForecastConfiguration forecastConfiguration = em.find(ForecastConfiguration.class, forecastConfigurationId); + ForecastConfiguration forecastConfiguration = + em.find(ForecastConfiguration.class, forecastConfigurationId); boolean multipleNew = false; // No forecastconfiguration found, assuming user want to register new - if(forecastConfiguration == null) - { + if (forecastConfiguration == null) { forecastConfiguration = new ForecastConfiguration(); - multipleNew = request.getParameter("multipleNew") != null - && request.getParameter("multipleNew").equals("true"); + multipleNew = request.getParameter("multipleNew") != null + && request.getParameter("multipleNew").equals("true"); } // Only superusers can view and edit forecasts from other organizations - if(! user.isSuperUser() && forecastConfiguration.getVipsLogicUserId() != null && !forecastConfiguration.getVipsLogicUserId().getOrganizationId().equals(user.getOrganizationId())) - { - response.sendError(403,"Access not authorized"); // HTTP Forbidden + if (!user.isSuperUser() && forecastConfiguration.getVipsLogicUserId() != null + && !forecastConfiguration.getVipsLogicUserId().getOrganizationId() + .equals(user.getOrganizationId())) { + response.sendError(403, "Access not authorized"); // HTTP Forbidden } // Only superusers can view and edit private forecasts from other users - else if(forecastConfiguration.getIsPrivate() && ! user.isSuperUser() && forecastConfiguration.getVipsLogicUserId() != null && !forecastConfiguration.getVipsLogicUserId().getUserId().equals(user.getUserId())) - { - response.sendError(403,"Access not authorized"); // HTTP Forbidden - } - else - { + else if (forecastConfiguration.getIsPrivate() && !user.isSuperUser() + && forecastConfiguration.getVipsLogicUserId() != null + && !forecastConfiguration.getVipsLogicUserId().getUserId().equals(user.getUserId())) { + response.sendError(403, "Access not authorized"); // HTTP Forbidden + } else { // TODO: More intelligent selection of locations, weather stations and users - if(user.isSuperUser()) - { - request.setAttribute("locationPointOfInterests", em.createNamedQuery("PointOfInterest.findAll").getResultList()); - request.setAttribute("weatherStationPointOfInterests", em.createNamedQuery("PointOfInterestWeatherStation.findAllByActivity").setParameter("active", Boolean.TRUE).getResultList()); - request.setAttribute("vipsLogicUsers", em.createNamedQuery("VipsLogicUser.findAll").getResultList()); - } - else - { - request.setAttribute("locationPointOfInterests", em.createNamedQuery("PointOfInterest.findByOrganizationId").setParameter("organizationId", user.getOrganizationId()).getResultList()); - request.setAttribute("weatherStationPointOfInterests", em.createNamedQuery("PointOfInterestWeatherStation.findByActivityAndOrganizationId").setParameter("active", Boolean.TRUE).setParameter("organizationId", user.getOrganizationId()).getResultList()); - request.setAttribute("vipsLogicUsers", em.createNamedQuery("VipsLogicUser.findByOrganizationId").setParameter("organizationId", user.getOrganizationId()).getResultList()); + if (user.isSuperUser()) { + request.setAttribute("locationPointOfInterests", + em.createNamedQuery("PointOfInterest.findAll").getResultList()); + request.setAttribute("weatherStationPointOfInterests", + em.createNamedQuery("PointOfInterestWeatherStation.findAllByActivity") + .setParameter("active", Boolean.TRUE).getResultList()); + request.setAttribute("vipsLogicUsers", + em.createNamedQuery("VipsLogicUser.findAll").getResultList()); + } else { + request.setAttribute("locationPointOfInterests", + em.createNamedQuery("PointOfInterest.findByOrganizationId") + .setParameter("organizationId", user.getOrganizationId()).getResultList()); + request.setAttribute("weatherStationPointOfInterests", + em.createNamedQuery("PointOfInterestWeatherStation.findByActivityAndOrganizationId") + .setParameter("active", Boolean.TRUE) + .setParameter("organizationId", user.getOrganizationId()).getResultList()); + request.setAttribute("vipsLogicUsers", + em.createNamedQuery("VipsLogicUser.findByOrganizationId") + .setParameter("organizationId", user.getOrganizationId()).getResultList()); } - request.setAttribute("currentLanguage", SessionLocaleUtil.getCurrentLocale(request).getLanguage()); + request.setAttribute("currentLanguage", + SessionLocaleUtil.getCurrentLocale(request).getLanguage()); request.setAttribute("forecastConfiguration", forecastConfiguration); - request.setAttribute("formId", multipleNew ? "forecastConfigurationMultipleNewForm" : "forecastConfigurationForm"); + request.setAttribute("formId", + multipleNew ? "forecastConfigurationMultipleNewForm" : "forecastConfigurationForm"); request.setAttribute("multipleNew", multipleNew); request.getSession().setAttribute("availableTimeZones", SystemTime.getAvailableTimeZones()); - request.getSession().setAttribute("defaultTimeZoneId", user.getOrganizationId().getDefaultTimeZone()); + request.getSession().setAttribute("defaultTimeZoneId", + user.getOrganizationId().getDefaultTimeZone()); // All organisms used for parent organism list request.setAttribute("allCrops", em.createNamedQuery("Organism.findAllCrops").getResultList()); request.setAttribute("allPests", em.createNamedQuery("Organism.findAllPests").getResultList()); // Hierarchy categories - request.setAttribute("hierarchyCategories", organismBean.getHierarchyCategoryNames(SessionLocaleUtil.getCurrentLocale(request))); + request.setAttribute("hierarchyCategories", + organismBean.getHierarchyCategoryNames(SessionLocaleUtil.getCurrentLocale(request))); request.setAttribute("modelInformations", forecastBean.getBatchableModels()); request.setAttribute("messageKey", request.getParameter("messageKey")); request.getRequestDispatcher("/forecastConfigurationForm.ftl").forward(request, response); } + } catch (NullPointerException | NumberFormatException ex) { + response.sendError(500, + "Invalid forecast configurationId " + request.getParameter("forecastConfigurationId")); } - catch(NullPointerException | NumberFormatException ex) - { - response.sendError(500, "Invalid forecast configurationId " + request.getParameter("forecastConfigurationId")); - } - } - else - { + } else { Long forecastConfigurationId = Long.valueOf(request.getParameter("forecastConfigurationId")); - ForecastConfiguration forecastConfiguration = em.find(ForecastConfiguration.class, forecastConfigurationId); - if(forecastConfiguration == null || forecastConfiguration.getVipsLogicUserId().getUserId().equals(user.getUserId())) - { - if(forecastConfiguration == null) - { + ForecastConfiguration forecastConfiguration = + em.find(ForecastConfiguration.class, forecastConfigurationId); + if (forecastConfiguration == null + || forecastConfiguration.getVipsLogicUserId().getUserId().equals(user.getUserId())) { + if (forecastConfiguration == null) { forecastConfiguration = new ForecastConfiguration(); forecastConfiguration.setIsPrivate(Boolean.TRUE); } request.setAttribute("currentLanguage", SessionLocaleUtil.getCurrentLocale(request).getLanguage()); request.setAttribute("forecastConfiguration", forecastConfiguration); - request.setAttribute("locationPointOfInterests", em.createNamedQuery("PointOfInterest.findByOrganizationId").setParameter("organizationId", user.getOrganizationId()).getResultList()); - request.setAttribute("weatherStationPointOfInterests", em.createNamedQuery("PointOfInterestWeatherStation.findByActivityAndOrganizationId").setParameter("active", Boolean.TRUE).setParameter("organizationId", user.getOrganizationId()).getResultList()); - request.setAttribute("formId","forecastConfigurationForm"); + request.setAttribute("locationPointOfInterests", + em.createNamedQuery("PointOfInterest.findByOrganizationId") + .setParameter("organizationId", user.getOrganizationId()).getResultList()); + request.setAttribute("weatherStationPointOfInterests", + em.createNamedQuery("PointOfInterestWeatherStation.findByActivityAndOrganizationId") + .setParameter("active", Boolean.TRUE) + .setParameter("organizationId", user.getOrganizationId()).getResultList()); + request.setAttribute("formId", "forecastConfigurationForm"); request.getSession().setAttribute("availableTimeZones", SystemTime.getAvailableTimeZones()); - request.getSession().setAttribute("defaultTimeZoneId", user.getOrganizationId().getDefaultTimeZone()); + request.getSession().setAttribute("defaultTimeZoneId", + user.getOrganizationId().getDefaultTimeZone()); request.setAttribute("allCrops", em.createNamedQuery("Organism.findAllCrops").getResultList()); request.setAttribute("allPests", em.createNamedQuery("Organism.findAllPests").getResultList()); // Hierarchy categories - request.setAttribute("hierarchyCategories", organismBean.getHierarchyCategoryNames(SessionLocaleUtil.getCurrentLocale(request))); - request.setAttribute("modelInformations", em.createNamedQuery("ModelInformation.findAll").getResultList()); + request.setAttribute("hierarchyCategories", + organismBean.getHierarchyCategoryNames(SessionLocaleUtil.getCurrentLocale(request))); + request.setAttribute("modelInformations", + em.createNamedQuery("ModelInformation.findAll").getResultList()); request.setAttribute("messageKey", request.getParameter("messageKey")); request.getRequestDispatcher("/forecastConfigurationForm.ftl").forward(request, response); - } - else - { - response.sendError(403,"Access not authorized"); + } else { + response.sendError(403, "Access not authorized"); } } } // Store forecast configuration(s) // Authorization: SUPERUSERS and ORGANIZATION ADMINS - else if(action.equals("forecastConfigurationFormSubmit")) - { - try - { + else if (action.equals("forecastConfigurationFormSubmit")) { + try { Long forecastConfigurationId = Long.valueOf(request.getParameter("forecastConfigurationId")); - ForecastConfiguration forecastConfiguration = em.find(ForecastConfiguration.class, forecastConfigurationId); + ForecastConfiguration forecastConfiguration = + em.find(ForecastConfiguration.class, forecastConfigurationId); // No forecastconfiguration found, assuming user want to register new - if(forecastConfiguration == null) - { + if (forecastConfiguration == null) { forecastConfiguration = new ForecastConfiguration(); } // Only superusers can view and edit forecasts from other organizations // Regular users can only edit own forecasts - if( - (! user.isSuperUser() && forecastConfiguration.getVipsLogicUserId() != null && !forecastConfiguration.getVipsLogicUserId().getOrganizationId().equals(user.getOrganizationId())) - || (! user.isSuperUser() && ! user.isOrganizationAdmin() && forecastConfiguration.getVipsLogicUserId() != null && !forecastConfiguration.getVipsLogicUserId().getUserId().equals(user.getUserId())) - ) - { - response.sendError(403,"Access not authorized"); // HTTP Forbidden - } - else - { - String formId = request.getParameter("multipleNew") != null && request.getParameter("multipleNew").equals("true") ? - "forecastConfigurationMultipleNewForm" - :"forecastConfigurationForm"; - FormValidation formValidation = FormValidator.validateForm(formId,request,getServletContext()); + if ((!user.isSuperUser() && forecastConfiguration.getVipsLogicUserId() != null + && !forecastConfiguration.getVipsLogicUserId().getOrganizationId() + .equals(user.getOrganizationId())) + || (!user.isSuperUser() && !user.isOrganizationAdmin() + && forecastConfiguration.getVipsLogicUserId() != null + && !forecastConfiguration.getVipsLogicUserId().getUserId().equals(user.getUserId()))) { + response.sendError(403, "Access not authorized"); // HTTP Forbidden + } else { + String formId = request.getParameter("multipleNew") != null + && request.getParameter("multipleNew").equals("true") + ? "forecastConfigurationMultipleNewForm" + : "forecastConfigurationForm"; + FormValidation formValidation = FormValidator.validateForm(formId, request, getServletContext()); LOGGER.debug("formValidation=" + formValidation.isValid()); // Also validation the model specific fields String modelId = formValidation.getFormField("modelId").getWebValue(); - FormValidation modelFieldFormValidation = FormValidator.validateForm("models/" + modelId, request, getServletContext()); + FormValidation modelFieldFormValidation = + FormValidator.validateForm("models/" + modelId, request, getServletContext()); // Additional input check: If the Grid data checkbox is not checked, a - if(formValidation.isValid() && modelFieldFormValidation.isValid()) - { - if(formId.equals("forecastConfigurationForm")) - { + if (formValidation.isValid() && modelFieldFormValidation.isValid()) { + if (formId.equals("forecastConfigurationForm")) { // Ensure regular users always enter private forecasts - if(! userBean.authorizeUser(user, VipsLogicRole.ORGANIZATION_ADMINISTRATOR, VipsLogicRole.SUPERUSER)) - { + if (!userBean.authorizeUser(user, VipsLogicRole.ORGANIZATION_ADMINISTRATOR, + VipsLogicRole.SUPERUSER)) { formValidation.getFormField("isPrivate").setWebValue("true"); } - forecastConfiguration = forecastBean.storeForecastConfiguration(forecastConfiguration, formValidation.getFormFields(), modelFieldFormValidation.getFormFields()); + forecastConfiguration = forecastBean.storeForecastConfiguration(forecastConfiguration, + formValidation.getFormFields(), modelFieldFormValidation.getFormFields()); // Store form config - //forecastBean.storeForecastModelConfigurations(forecastConfiguration, modelFieldFormValidation.getFormFields()); + // forecastBean.storeForecastModelConfigurations(forecastConfiguration, + // modelFieldFormValidation.getFormFields()); // TODO: Store model specific fields // First: Delete all o request.setAttribute("messageKey", request.getParameter("formConfigurationUpdated")); - response.sendRedirect(new StringBuilder(Globals.PROTOCOL + "://").append(ServletUtil.getServerName(request)).append("/forecastConfiguration?action=viewForecastConfiguration&forecastConfigurationId=").append(forecastConfiguration.getForecastConfigurationId()).append("&messageKey=").append("forecastConfigurationUpdated").toString()); - } - else - { - for(String optionVal:formValidation.getFormField("weatherStationPointOfInterestIds").getWebValues()) - { + response.sendRedirect(new StringBuilder(Globals.PROTOCOL + "://") + .append(ServletUtil.getServerName(request)) + .append("/forecastConfiguration?action=viewForecastConfiguration&forecastConfigurationId=") + .append(forecastConfiguration.getForecastConfigurationId()).append("&messageKey=") + .append("forecastConfigurationUpdated").toString()); + } else { + for (String optionVal : formValidation.getFormField("weatherStationPointOfInterestIds") + .getWebValues()) { Integer weatherStationPointOfInterestId = Integer.valueOf(optionVal); - forecastBean.storeNewMultipleForecastConfiguration(weatherStationPointOfInterestId, formValidation.getFormFields(), modelFieldFormValidation.getFormFields()); + forecastBean.storeNewMultipleForecastConfiguration(weatherStationPointOfInterestId, + formValidation.getFormFields(), modelFieldFormValidation.getFormFields()); } - request.setAttribute("messageKey", request.getParameter("multipleForecastConfigurationsCreated")); - response.sendRedirect(new StringBuilder(Globals.PROTOCOL + "://").append(ServletUtil.getServerName(request)).append("/forecastConfiguration?messageKey=").append("multipleForecastConfigurationsCreated").toString()); + request.setAttribute("messageKey", + request.getParameter("multipleForecastConfigurationsCreated")); + response.sendRedirect(new StringBuilder(Globals.PROTOCOL + "://") + .append(ServletUtil.getServerName(request)) + .append("/forecastConfiguration?messageKey=") + .append("multipleForecastConfigurationsCreated").toString()); } - } - else - { + } else { // Return to form with error messages request.setAttribute("formValidation", formValidation); // We must get date formats! - Map<String, FormField> formFields = FormValidator.getFormFields("forecastConfigurationForm",getServletContext()); + Map<String, FormField> formFields = + FormValidator.getFormFields("forecastConfigurationForm", getServletContext()); // TODO: More intelligent selection of locations, weather stations and users - request.setAttribute("locationPointOfInterests", em.createNamedQuery("PointOfInterest.findAll").getResultList()); - request.setAttribute("weatherStationPointOfInterests", em.createNamedQuery("PointOfInterestWeatherStation.findAll").getResultList()); - request.setAttribute("vipsLogicUsers", em.createNamedQuery("VipsLogicUser.findAll").getResultList()); + request.setAttribute("formId", "forecastConfigurationForm"); + request.setAttribute("allCrops", em.createNamedQuery("Organism.findAllCrops").getResultList()); + request.setAttribute("allPests", em.createNamedQuery("Organism.findAllPests").getResultList()); + request.setAttribute("locationPointOfInterests", + em.createNamedQuery("PointOfInterest.findAll").getResultList()); + request.setAttribute("weatherStationPointOfInterests", + em.createNamedQuery("PointOfInterestWeatherStation.findAll").getResultList()); + request.setAttribute("vipsLogicUsers", + em.createNamedQuery("VipsLogicUser.findAll").getResultList()); request.setAttribute("dateStart_dateFormat", formFields.get("dateStart").getDateFormat()); request.setAttribute("dateEnd_dateFormat", formFields.get("dateEnd").getDateFormat()); request.getSession().setAttribute("availableTimeZones", SystemTime.getAvailableTimeZones()); - request.getSession().setAttribute("defaultTimeZoneId", user.getOrganizationId().getDefaultTimeZone()); - request.setAttribute("modelInformations", em.createNamedQuery("ModelInformation.findAll").getResultList()); - request.setAttribute("currentLanguage", SessionLocaleUtil.getCurrentLocale(request).getLanguage()); + request.getSession().setAttribute("defaultTimeZoneId", + user.getOrganizationId().getDefaultTimeZone()); + // Hierarchy categories + request.setAttribute("hierarchyCategories", + organismBean.getHierarchyCategoryNames(SessionLocaleUtil.getCurrentLocale(request))); + request.setAttribute("modelInformations", + em.createNamedQuery("ModelInformation.findAll").getResultList()); + request.setAttribute("currentLanguage", + SessionLocaleUtil.getCurrentLocale(request).getLanguage()); request.setAttribute("forecastConfiguration", forecastConfiguration); request.getRequestDispatcher("/forecastConfigurationForm.ftl").forward(request, response); } } - } - catch(NullPointerException | NumberFormatException | FormValidationException ex) - { + } catch (NullPointerException | NumberFormatException | FormValidationException ex) { ex.printStackTrace(); - if(ex instanceof NumberFormatException) - { - response.sendError(500, "Invalid forecast configurationId " + request.getParameter("forecastConfigurationId")); - } - else - { + if (ex instanceof NumberFormatException) { + response.sendError(500, + "Invalid forecast configurationId " + request.getParameter("forecastConfigurationId")); + } else { response.sendError(500, ex.getMessage()); } } } // Delete forecast configuration // Authorization: SUPERUSERS and ORGANIZATION ADMINS OR regular users owning the forecast config - else if(action.equals("deleteForecastConfiguration")) - { + else if (action.equals("deleteForecastConfiguration")) { Long forecastConfigurationId = Long.valueOf(request.getParameter("forecastConfigurationId")); ForecastConfiguration forecastConfiguration = em.find(ForecastConfiguration.class, forecastConfigurationId); - if( - userBean.authorizeUser(user, VipsLogicRole.ORGANIZATION_ADMINISTRATOR, VipsLogicRole.SUPERUSER) - || user.getUserId().equals(forecastConfiguration.getVipsLogicUserId().getUserId()) - ) - { + if (userBean.authorizeUser(user, VipsLogicRole.ORGANIZATION_ADMINISTRATOR, VipsLogicRole.SUPERUSER) + || user.getUserId().equals(forecastConfiguration.getVipsLogicUserId().getUserId())) { // Only superusers can delete forecasts from other organizations - if(! user.isSuperUser() && forecastConfiguration.getVipsLogicUserId() != null && !forecastConfiguration.getVipsLogicUserId().getOrganizationId().equals(user.getOrganizationId())) - { - response.sendError(403,"Access not authorized"); // HTTP Forbidden + if (!user.isSuperUser() && forecastConfiguration.getVipsLogicUserId() != null && !forecastConfiguration + .getVipsLogicUserId().getOrganizationId().equals(user.getOrganizationId())) { + response.sendError(403, "Access not authorized"); // HTTP Forbidden return; } - try - { + try { forecastBean.deleteForecastConfiguration(forecastConfigurationId); - response.sendRedirect(new StringBuilder(Globals.PROTOCOL + "://").append(ServletUtil.getServerName(request)).append("/forecastConfiguration?").append("&messageKey=").append("forecastConfigurationDeleted").toString()); - } - catch(NullPointerException | NumberFormatException ex) - { - response.sendError(500, "Invalid forecast configurationId " + request.getParameter("forecastConfigurationId")); + response.sendRedirect(new StringBuilder(Globals.PROTOCOL + "://") + .append(ServletUtil.getServerName(request)).append("/forecastConfiguration?") + .append("&messageKey=").append("forecastConfigurationDeleted").toString()); + } catch (NullPointerException | NumberFormatException ex) { + response.sendError(500, + "Invalid forecast configurationId " + request.getParameter("forecastConfigurationId")); } - } - else - { - response.sendError(403,"Access not authorized"); // HTTP Forbidden + } else { + response.sendError(403, "Access not authorized"); // HTTP Forbidden } } } - // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code."> + // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the + // code."> /** * Handles the HTTP <code>GET</code> method. * diff --git a/src/main/webapp/templates/forecastConfigurationForm.ftl b/src/main/webapp/templates/forecastConfigurationForm.ftl index 9c1967b32007fd668814455baae490b4aefaa11c..08988f90df2d15e0460725a5ef29d95d2b74cc2c 100755 --- a/src/main/webapp/templates/forecastConfigurationForm.ftl +++ b/src/main/webapp/templates/forecastConfigurationForm.ftl @@ -38,23 +38,27 @@ <script type="module"> import MapModal from '/js/mapModal.js'; const selectLocationElement = document.querySelector('select[name="locationPointOfInterestId"]'); + const selectWeatherstationElement = document.querySelector('select[name="weatherStationPointOfInterestId"]') != null ? document.querySelector('select[name="weatherStationPointOfInterestId"]') : document.querySelector('select[name="weatherStationPointOfInterestIdDisabled"]'); + console.info(selectWeatherstationElement); + + window.selectedPoiId = <#if forecastConfiguration.locationPointOfInterestId??>${forecastConfiguration.locationPointOfInterestId.pointOfInterestId!"undefined"}<#else>undefined</#if>; + window.selectedWeatherstationId = <#if forecastConfiguration.weatherStationPointOfInterestId??>${forecastConfiguration.weatherStationPointOfInterestId.pointOfInterestId!"undefined"}<#else>undefined</#if>; // Read the list of locations into javascript array, to be able to dynamically manipulate it - let locationList = [ + window.locationList = [ <#list locationPointOfInterests as poi> { "pointOfInterestId": "${poi.pointOfInterestId}", - "name": "${poi.name?json_string}" + "name": "${poi.name?json_string}", + "pointOfInterestTypeId": ${poi.pointOfInterestTypeId} }, </#list> ]; - renderPoiSelect(selectLocationElement, locationList); - // Populate select list for point of interest -> NOT GENERAL! Default value is specific to location. - function renderPoiSelect(selectElement, elementList, selectedId) { - selectElement.innerHTML = ''; - const createOption = (value, text, isSelected = false) => { + + + const createOption = (value, text, isSelected = false) => { const option = document.createElement('option'); option.value = value; option.textContent = text; @@ -62,6 +66,50 @@ return option; }; + renderPoiSelect(selectLocationElement, locationList, selectedPoiId); + renderWeatherstationSelect(selectWeatherstationElement, locationList, selectedWeatherstationId); + // Setting weather station select list state correct on page load + <#if isGridForecastSupported> + handleUseGridWeatherDataClicked(document.getElementById("useGridWeatherData")<#if forecastConfiguration.weatherStationPointOfInterestId?has_content && forecastConfiguration.weatherStationPointOfInterestId.pointOfInterestId?has_content>,${forecastConfiguration.weatherStationPointOfInterestId.pointOfInterestId}</#if>); + </#if> + + function renderWeatherstationSelect(selectElement, elementList, selectedId) + { + selectElement.options.length = 0; + + <#if isGridForecastSupported> + // Add default option + selectElement.appendChild(createOption( + "-2", + "${i18nBundle.doNotUse} ${i18nBundle.weatherStationPointOfInterestId?lower_case}", + !selectedId + )); + </#if> + + // Add default option + selectElement.appendChild(createOption( + "-1", + "${i18nBundle.pleaseSelect} ${i18nBundle.weatherStationPointOfInterestId?lower_case}", + !selectedId + )); + + // Add all locations that are weatherstations + elementList.forEach(poi => { + if(poi.pointOfInterestTypeId == POI_TYPE_WEATHERSTATION) + { + selectElement.appendChild(createOption( + poi.pointOfInterestId, + poi.name, + selectedId && poi.pointOfInterestId == selectedId + )); + } + }); + } + + // Populate select list for point of interest -> NOT GENERAL! Default value is specific to location. + function renderPoiSelect(selectElement, elementList, selectedId) { + selectElement.innerHTML = ''; + // Add default option selectElement.appendChild(createOption( "-1", @@ -79,7 +127,7 @@ }); } - function selectPoi(selectElement, selectedId) { + window.selectPoi = function(selectElement, selectedId) { if (selectedId) { const optionIndex = Array.from(selectElement.options).findIndex(option => option.value == selectedId); if (optionIndex !== -1) { @@ -103,6 +151,7 @@ } else { selectPoi(selectLocationElement, poiData.pointOfInterestId); } + handleLocationChanged(); } function persistNewLocation(poiData) { @@ -119,6 +168,8 @@ .then(poi => { locationList.push(poi); renderPoiSelect(selectLocationElement, locationList, poi.pointOfInterestId); + // Assuming that this is not a weather station, since weather stations cannot be created using the + // map, the user must have created a .... MAYBE HANDLED AUTOMATICALLY?? by the change event?? console.info("Point of interest successfully persisted", poi); }) .catch(error => { @@ -152,6 +203,7 @@ </script> <script type="text/javascript"> + const POI_TYPE_WEATHERSTATION = 1; $(document).ready(function() { // Make sure that there is a date picker present for HTML5 // date input fields @@ -309,7 +361,7 @@ } } }; - var handleUseGridWeatherDataClicked = function(theCheckBox, weatherStationPointOfInterestId) { + window.handleUseGridWeatherDataClicked = function(theCheckBox, weatherStationPointOfInterestId) { weatherStationList = document.getElementById("weatherStationPointOfInterestId"); weatherStationPointOfInterestIdHiddenField = document.getElementById("weatherStationPointOfInterestIdHidden"); if(theCheckBox.checked) @@ -347,18 +399,35 @@ } }; - // Setting weather station select list state correct on page load - <#if isGridForecastSupported> - handleUseGridWeatherDataClicked(document.getElementById("useGridWeatherData")<#if forecastConfiguration.weatherStationPointOfInterestId?has_content && forecastConfiguration.weatherStationPointOfInterestId.pointOfInterestId?has_content>,${forecastConfiguration.weatherStationPointOfInterestId.pointOfInterestId}</#if>); - </#if> + let handleLocationChanged = function(){ + // Which location has been selected? + let selectedPoiId = document.getElementById("locationPointOfInterestId").options[document.getElementById("locationPointOfInterestId").selectedIndex].value; + if(selectedPoiId <= 0) + { + document.getElementById("weatherDatasourceFieldset").disabled = true; + weatherstationSelect.selectedIndex = 0; + return; + } // Enable the weather datasource fieldset document.getElementById("weatherDatasourceFieldset").disabled=false; - // Which location has been selected? - // If weather station -> Preselect weather station, set grid checkbox to false - // Else: Deselect weather station (if any), set grid checkbox to true + + + let selectedLocation = undefined; + for(let i=0; i<locationList.length;i++) + { + if(locationList[i].pointOfInterestId == selectedPoiId) + { + selectedLocation = locationList[i]; + } + } + <#if isGridForecastSupported> + let gridCheckBox = document.getElementById("useGridWeatherData"); + gridCheckBox.checked = (selectedLocation.pointOfInterestTypeId != POI_TYPE_WEATHERSTATION); + handleUseGridWeatherDataClicked(gridCheckBox, (selectedLocation.pointOfInterestTypeId == POI_TYPE_WEATHERSTATION ? selectedLocation.pointOfInterestId: undefined)); + </#if> } </script> </#macro> @@ -451,22 +520,15 @@ </div> <span class="help-block" id="${formId}_locationPointOfInterestId_validation"></span> </div> - <fieldset id="weatherDatasourceFieldset" disabled> - <legend>${i18nBundle.weatherDatasource}</legend> - <p>Velg sted ovenfor først, og velg deretter værdatakilde.</p> + <div class="alert alert-info" role="alert">Velg sted ovenfor først, og velg deretter værdatakilde. Du kan enten velge en av de tilgjengelige værstasjonene, + eller at ditt valgte steds plassering brukes til å hente værdata fra en ekstern tjeneste. Hvis ditt sted ligger nær + en av værstasjonene, gir det som oftest den beste kvaliteten på værdata.</div> + <fieldset id="weatherDatasourceFieldset" <#if !forecastConfiguration.weatherStationPointOfInterestId?has_content>disabled</#if>> + <legend style="margin-bottom: 0px;">${i18nBundle.weatherDatasource}</legend> <div class="form-group"> <label for="weatherStationPointOfInterestId">${i18nBundle.weatherStationPointOfInterestId}</label> <select class="form-control" id="weatherStationPointOfInterestId" name="weatherStationPointOfInterestId" onblur="if(!document.getElementById('useGridWeatherData').checked) {validateField(this);}"> - <#if isGridForecastSupported> - <option value="-2">${i18nBundle.doNotUse} ${i18nBundle.weatherStationPointOfInterestId?lower_case}</option> - </#if> - <option value="-1"<#if !forecastConfiguration.weatherStationPointOfInterestId?has_content && !forecastConfiguration.useGridWeatherData> selected="selected"</#if>>${i18nBundle.pleaseSelect} ${i18nBundle.weatherStationPointOfInterestId?lower_case}</option> - <#list weatherStationPointOfInterests?sort_by("name") as poi> - <option value="${poi.pointOfInterestId}"<#if - forecastConfiguration.weatherStationPointOfInterestId?has_content - && forecastConfiguration.weatherStationPointOfInterestId.pointOfInterestId?has_content - && poi.pointOfInterestId == forecastConfiguration.weatherStationPointOfInterestId.pointOfInterestId> selected="selected"</#if>>${poi.name}</option> - </#list> + </select> <span class="help-block" id="${formId}_weatherStationPointOfInterestId_validation"></span> </div>