Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • VIPS/VIPSLogic
1 result
Select Git revision
Show changes
Showing
with 1514 additions and 1167 deletions
...@@ -27,13 +27,13 @@ import java.text.MessageFormat; ...@@ -27,13 +27,13 @@ import java.text.MessageFormat;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import javax.ejb.EJB; import jakarta.ejb.EJB;
import javax.persistence.EntityManager; import jakarta.persistence.EntityManager;
import javax.persistence.PersistenceContext; import jakarta.persistence.PersistenceContext;
import javax.servlet.ServletException; import jakarta.servlet.ServletException;
import javax.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import no.nibio.vips.logic.controller.session.SchedulingBean; import no.nibio.vips.logic.controller.session.SchedulingBean;
import no.nibio.vips.logic.controller.session.UserBean; import no.nibio.vips.logic.controller.session.UserBean;
import no.nibio.vips.logic.entity.TaskHistory; import no.nibio.vips.logic.entity.TaskHistory;
......
...@@ -31,15 +31,15 @@ import java.util.Map; ...@@ -31,15 +31,15 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.ejb.EJB; import jakarta.ejb.EJB;
import javax.persistence.EntityManager; import jakarta.persistence.EntityManager;
import javax.persistence.NoResultException; import jakarta.persistence.NoResultException;
import javax.persistence.NonUniqueResultException; import jakarta.persistence.NonUniqueResultException;
import javax.persistence.PersistenceContext; import jakarta.persistence.PersistenceContext;
import javax.servlet.ServletException; import jakarta.servlet.ServletException;
import javax.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import no.nibio.vips.i18n.LanguageUtil; import no.nibio.vips.i18n.LanguageUtil;
import no.nibio.vips.logic.controller.session.DeleteUserException; import no.nibio.vips.logic.controller.session.DeleteUserException;
import no.nibio.vips.logic.controller.session.UserBean; import no.nibio.vips.logic.controller.session.UserBean;
...@@ -51,6 +51,8 @@ import no.nibio.vips.logic.entity.VipsLogicRole; ...@@ -51,6 +51,8 @@ import no.nibio.vips.logic.entity.VipsLogicRole;
import no.nibio.vips.logic.entity.VipsLogicUser; import no.nibio.vips.logic.entity.VipsLogicUser;
import no.nibio.vips.logic.entity.misc.UserResources; import no.nibio.vips.logic.entity.misc.UserResources;
import no.nibio.vips.logic.i18n.SessionLocaleUtil; import no.nibio.vips.logic.i18n.SessionLocaleUtil;
import no.nibio.vips.logic.modules.barkbeetle.BarkbeetleBean;
import no.nibio.vips.logic.modules.barkbeetle.SeasonTrapsite;
import no.nibio.vips.logic.util.Globals; import no.nibio.vips.logic.util.Globals;
import no.nibio.vips.util.ServletUtil; import no.nibio.vips.util.ServletUtil;
import no.nibio.web.forms.FormField; import no.nibio.web.forms.FormField;
...@@ -71,6 +73,9 @@ public class UserController extends HttpServlet { ...@@ -71,6 +73,9 @@ public class UserController extends HttpServlet {
@EJB @EJB
UserBean userBean; UserBean userBean;
@EJB
BarkbeetleBean barkbeetleBean;
/** /**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code> * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
...@@ -406,9 +411,12 @@ public class UserController extends HttpServlet { ...@@ -406,9 +411,12 @@ public class UserController extends HttpServlet {
Integer userId = Integer.valueOf(request.getParameter("userId")); Integer userId = Integer.valueOf(request.getParameter("userId"));
VipsLogicUser viewUser = em.find(VipsLogicUser.class, userId); VipsLogicUser viewUser = em.find(VipsLogicUser.class, userId);
UserResources userResources = userBean.getUserResources(viewUser); UserResources userResources = userBean.getUserResources(viewUser);
// Barkbeetle module dependencies
List<SeasonTrapsite> userSeasonTrapsites = barkbeetleBean.getSeasonTrapsites(viewUser);
// If some resources connected, render form, otherwise, route to user delete // If some resources connected, render form, otherwise, route to user delete
if(userResources.isEmpty()) if(userResources.isEmpty() && userSeasonTrapsites.isEmpty())
{ {
response.sendRedirect(new StringBuilder(Globals.PROTOCOL + "://").append(ServletUtil.getServerName(request)).append("/user").append("?action=deleteUser&userId=").append(userId).toString()); response.sendRedirect(new StringBuilder(Globals.PROTOCOL + "://").append(ServletUtil.getServerName(request)).append("/user").append("?action=deleteUser&userId=").append(userId).toString());
} }
...@@ -423,7 +431,9 @@ public class UserController extends HttpServlet { ...@@ -423,7 +431,9 @@ public class UserController extends HttpServlet {
request.setAttribute("viewUser", viewUser); request.setAttribute("viewUser", viewUser);
request.setAttribute("userResources", userResources); request.setAttribute("userResources", userResources);
java.util.Collections.sort(users);
request.setAttribute("users", users); request.setAttribute("users", users);
request.setAttribute("userBarkbeetleSeasonTrapsites", userSeasonTrapsites);
request.setAttribute("errorMsg", request.getParameter("errorMsg")); request.setAttribute("errorMsg", request.getParameter("errorMsg"));
request.getRequestDispatcher("/userDeleteForm.ftl").forward(request, response); request.getRequestDispatcher("/userDeleteForm.ftl").forward(request, response);
} }
...@@ -450,7 +460,9 @@ public class UserController extends HttpServlet { ...@@ -450,7 +460,9 @@ public class UserController extends HttpServlet {
// Are there resources connected to this user? // Are there resources connected to this user?
UserResources userResources = userBean.getUserResources(viewUser); UserResources userResources = userBean.getUserResources(viewUser);
if(! userResources.isEmpty()) // Barkbeetle module dependencies
List<SeasonTrapsite> userSeasonTrapsites = barkbeetleBean.getSeasonTrapsites(viewUser);
if(! userResources.isEmpty() || ! userSeasonTrapsites.isEmpty())
{ {
boolean resourcesTransferred = false; boolean resourcesTransferred = false;
try try
...@@ -460,6 +472,7 @@ public class UserController extends HttpServlet { ...@@ -460,6 +472,7 @@ public class UserController extends HttpServlet {
if(transferToUser != null) if(transferToUser != null)
{ {
userBean.transferUserResources(viewUser,transferToUser); userBean.transferUserResources(viewUser,transferToUser);
barkbeetleBean.transferSeasonTrapsites(viewUser,transferToUser);
resourcesTransferred = true; resourcesTransferred = true;
} }
} }
......
/*
* Copyright (c) 2024 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 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/>.
*
*/
package no.nibio.vips.logic.controller.servlet;
import java.io.IOException;
import java.util.List;
import jakarta.ejb.EJB;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import no.nibio.vips.gis.LonLatStringFormatException;
import no.nibio.vips.logic.controller.session.PointOfInterestBean;
import no.nibio.vips.logic.entity.VipsLogicUser;
import no.nibio.vips.logic.entity.WeatherStationDataSource;
import no.nibio.vips.logic.util.Globals;
import no.nibio.vips.logic.util.SystemTime;
import no.nibio.vips.util.ServletUtil;
import no.nibio.web.forms.FormValidation;
import no.nibio.web.forms.FormValidationException;
import no.nibio.web.forms.FormValidator;;
/**
* Handles actions regarding listing and modifying weather station data sources
*
* @copyright 2024 <a href="http://www.nibio.no/">NIBIO</a>
* @author Tor-Einar Skog <tor-einar.skog@nibio.no>
*/
public class WeatherStationDataSourceController extends HttpServlet{
private static Logger LOGGER = LoggerFactory.getLogger(WeatherStationDataSourceController.class);
@EJB
PointOfInterestBean poiBean;
/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
VipsLogicUser user = (VipsLogicUser) request.getSession().getAttribute("user");
// Basic authorization
if(!user.isSuperUser() && ! user.isOrganizationAdmin()){
response.sendError(403,"Access not authorized");
return;
}
String action = request.getParameter("action");
if(action == null)
{
List<WeatherStationDataSource> wsDataSources = poiBean.getWeatherStationDataSources();
request.setAttribute("messageKey", request.getParameter("messageKey") != null ? request.getParameter("messageKey") : null);
request.setAttribute("weatherStationDataSources", wsDataSources);
request.getRequestDispatcher("/weatherStationDataSourceList.ftl").forward(request, response);
}
else if(action.equals("editWeatherStationDataSource") || action.equals("newWeatherStationDataSource"))
{
WeatherStationDataSource weatherStationDataSource = null;
try
{
weatherStationDataSource = poiBean.getWeatherStationDataSource(Integer.valueOf(request.getParameter("weatherStationDataSourceId")));
}
catch(NullPointerException | NumberFormatException ex){}
if(weatherStationDataSource == null)
{
LOGGER.debug("Could not find weather data source with ID = " + request.getParameter("weatherStationDataSourceId"));
weatherStationDataSource = new WeatherStationDataSource();
}
request.setAttribute("messageKey", request.getParameter("messageKey") != null ? request.getParameter("messageKey") : null);
request.setAttribute("weatherStationDataSource", weatherStationDataSource);
request.getRequestDispatcher("/weatherStationDataSourceForm.ftl").forward(request, response);
}
else if(action.equals("weatherStationDataSourceFormSubmit"))
{
try
{
// Check that the provided id is either -1 or it already exists
Integer weatherStationDataSourceId = null;
WeatherStationDataSource weatherStationDataSource;
try
{
weatherStationDataSourceId = Integer.valueOf(request.getParameter("weatherStationDataSourceId"));
}
catch(NullPointerException | NumberFormatException ex)
{
response.sendError(400,"Wrong format of id for weather station data source");
}
if(weatherStationDataSourceId < 0)
{
weatherStationDataSource = new WeatherStationDataSource();
}
else
{
weatherStationDataSource = poiBean.getWeatherStationDataSource(weatherStationDataSourceId);
if(weatherStationDataSource == null)
{
response.sendError(404,"Could not find weather station data source with id=" + weatherStationDataSourceId);
}
}
FormValidation formValidation = FormValidator.validateForm("weatherStationDataSourceForm", request, getServletContext());
if(formValidation.isValid())
{
weatherStationDataSource.setName(formValidation.getFormField("name").getWebValue());
weatherStationDataSource.setDefaultDescription(formValidation.getFormField("defaultDescription").getWebValue());
weatherStationDataSource.setUri(formValidation.getFormField("uri").getWebValue());
weatherStationDataSource.setDatafetchUriExpression(formValidation.getFormField("datafetchUriExpression").getWebValue());
weatherStationDataSource.setInfoUriExpression(formValidation.getFormField("infoUriExpression").getWebValue());
weatherStationDataSource.setIsGrid(formValidation.getFormField("isGrid").getWebValue() != null);
weatherStationDataSource = poiBean.storeWeatherStationDataSource(weatherStationDataSource);
response.sendRedirect(
Globals.PROTOCOL + "://" + ServletUtil.getServerName(request)
+ "/weatherstationdatasource?action=editWeatherStationDataSource&weatherStationDataSourceId=" + weatherStationDataSource.getWeatherStationDataSourceId()
+ "&messageKey=weatherStationDataSourceStored"
);
}
else
{
request.setAttribute("formValidation", formValidation);
request.setAttribute("weatherStationDataSource", weatherStationDataSource);
LOGGER.debug("Form NOT valid. Dispatching");
request.getRequestDispatcher("/weatherStationDataSourceForm.ftl").forward(request, response);
}
}
catch(FormValidationException ex)
{
ex.printStackTrace();
response.sendError(500, ex.getClass().toString() + ": " + ex.getMessage());
}
}
else if(action.equals("deleteWeatherStationDataSource"))
{
try
{
Integer weatherStationDataSourceId = Integer.valueOf(request.getParameter("weatherStationDataSourceId"));
WeatherStationDataSource weatherStationDataSource = poiBean.getWeatherStationDataSource(weatherStationDataSourceId);
if(weatherStationDataSource == null)
{
response.sendError(404,"Could not find weather station data source with id=" + weatherStationDataSourceId);
}
// Check: Can it be deleted? Not if organizations or weatherStations refer to it
if(poiBean.isweatherStationDataSourceDeleteable(weatherStationDataSource))
{
poiBean.deleteWeatherStationDataSource(weatherStationDataSource);
// Redirect to list from which the deleted item has been removed
response.sendRedirect(
Globals.PROTOCOL + "://" + ServletUtil.getServerName(request)
+ "/weatherstationdatasource?messageKey=weatherStationDataSourceDeleted"
);
}
else
{
response.sendError(403,weatherStationDataSource.getName() + " is in use by one or more organizations, so it cannot be deleted. Hit the browser's back button return to your form.");
}
}
catch(NullPointerException | NumberFormatException ex)
{
response.sendError(400,"Wrong format of id for weather station data source");
}
}
}
// <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.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP <code>POST</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Returns a short description of the servlet.
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
}
/* /*
* Copyright (c) 2015 NIBIO <http://www.nibio.no/>. * Copyright (c) 2015 NIBIO <http://www.nibio.no/>.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
* it under the terms of the GNU Affero General Public License as published by * Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* the Free Software Foundation, either version 3 of the License, or * later version.
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* but WITHOUT ANY WARRANTY; without even the implied warranty of * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * details.
* GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License along with this program. If not, see
* along with this program. If not, see <https://www.gnu.org/licenses/>. * <https://www.gnu.org/licenses/>.
* *
*/ */
package no.nibio.vips.logic.controller.session; package no.nibio.vips.logic.controller.session;
import com.fasterxml.jackson.databind.JsonNode; import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import jakarta.ejb.EJB;
import jakarta.ejb.Stateless;
import jakarta.persistence.EntityManager;
import jakarta.persistence.NoResultException;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;
import jakarta.ws.rs.ProcessingException;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.GenericType;
import jakarta.ws.rs.core.Response;
import org.apache.commons.lang.StringUtils;
import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.JsonNode;
import de.micromata.opengis.kml.v_2_2_0.Coordinate; import de.micromata.opengis.kml.v_2_2_0.Coordinate;
import de.micromata.opengis.kml.v_2_2_0.Data; import de.micromata.opengis.kml.v_2_2_0.Data;
import de.micromata.opengis.kml.v_2_2_0.Document; import de.micromata.opengis.kml.v_2_2_0.Document;
...@@ -32,30 +57,6 @@ import de.micromata.opengis.kml.v_2_2_0.Placemark; ...@@ -32,30 +57,6 @@ import de.micromata.opengis.kml.v_2_2_0.Placemark;
import de.micromata.opengis.kml.v_2_2_0.Point; import de.micromata.opengis.kml.v_2_2_0.Point;
import de.micromata.opengis.kml.v_2_2_0.Units; import de.micromata.opengis.kml.v_2_2_0.Units;
import de.micromata.opengis.kml.v_2_2_0.Vec2; import de.micromata.opengis.kml.v_2_2_0.Vec2;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.ws.rs.ProcessingException;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.Response;
import no.nibio.vips.coremanager.service.ManagerResource; import no.nibio.vips.coremanager.service.ManagerResource;
import no.nibio.vips.entity.ModelConfiguration; import no.nibio.vips.entity.ModelConfiguration;
import no.nibio.vips.entity.ModelRunRequest; import no.nibio.vips.entity.ModelRunRequest;
...@@ -81,9 +82,6 @@ import no.nibio.vips.logic.util.RunModelException; ...@@ -81,9 +82,6 @@ import no.nibio.vips.logic.util.RunModelException;
import no.nibio.vips.logic.util.SystemTime; import no.nibio.vips.logic.util.SystemTime;
import no.nibio.vips.util.WeatherUtil; import no.nibio.vips.util.WeatherUtil;
import no.nibio.web.forms.FormField; import no.nibio.web.forms.FormField;
import org.apache.commons.lang.StringUtils;
import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;
import org.slf4j.LoggerFactory;
/** /**
* @copyright 2013-2022 <a href="http://www.nibio.no/">NIBIO</a> * @copyright 2013-2022 <a href="http://www.nibio.no/">NIBIO</a>
...@@ -94,179 +92,163 @@ public class ForecastBean { ...@@ -94,179 +92,163 @@ public class ForecastBean {
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(ForecastBean.class); private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(ForecastBean.class);
@PersistenceContext(unitName="VIPSLogic-PU") @PersistenceContext(unitName = "VIPSLogic-PU")
EntityManager em; EntityManager em;
@EJB @EJB
ForecastBean forecastBean; ForecastBean forecastBean;
@EJB @EJB
UserBean userBean; UserBean userBean;
/** /**
* Returns all forecast results. * Returns all forecast results.
* @return *
* @return
*/ */
public List<ForecastResult> getForecastResults() public List<ForecastResult> getForecastResults() {
{
return em.createNamedQuery("ForecastResult.findAll").getResultList(); return em.createNamedQuery("ForecastResult.findAll").getResultList();
} }
public List<ForecastResult> getForecastResults(Long forecastConfigurationId) public List<ForecastResult> getForecastResults(Long forecastConfigurationId) {
{ // ForecastConfiguration config = this.getForecastConfiguration(forecastConfigurationId);
//ForecastConfiguration config = this.getForecastConfiguration(forecastConfigurationId);
Query q = em.createNamedQuery("ForecastResult.findByForecastConfigurationId"); Query q = em.createNamedQuery("ForecastResult.findByForecastConfigurationId");
q.setParameter("forecastConfigurationId", forecastConfigurationId); q.setParameter("forecastConfigurationId", forecastConfigurationId);
return q.getResultList(); return q.getResultList();
} }
/** /**
* *
* @param forecastConfiguration * @param forecastConfiguration
* @param user * @param user
* @return * @return
*/ */
public boolean isUserAuthorizedForForecastConfiguration(ForecastConfiguration forecastConfiguration, VipsLogicUser user) public boolean isUserAuthorizedForForecastConfiguration(ForecastConfiguration forecastConfiguration,
{ VipsLogicUser user) {
// Public forecasts are always OK for everyone to view // Public forecasts are always OK for everyone to view
if(!forecastConfiguration.getIsPrivate()) if (!forecastConfiguration.getIsPrivate()) {
{
return true; return true;
} }
// Private forecasts are only viewable by owner or super users / orgadmins // Private forecasts are only viewable by owner or super users / orgadmins
return user != null && (user.isSuperUser() || user.isOrganizationAdmin() || user.getUserId().equals( forecastConfiguration.getVipsLogicUserId().getUserId())); return user != null && (user.isSuperUser() || user.isOrganizationAdmin()
|| user.getUserId().equals(forecastConfiguration.getVipsLogicUserId().getUserId()));
} }
public boolean isUserAuthorizedForForecastConfiguration(Long forecastConfigurationId, String userUUID) public boolean isUserAuthorizedForForecastConfiguration(Long forecastConfigurationId, String userUUID) {
{
// Authentication // Authentication
ForecastConfiguration fc = em.find(ForecastConfiguration.class, forecastConfigurationId); ForecastConfiguration fc = em.find(ForecastConfiguration.class, forecastConfigurationId);
if(fc == null) if (fc == null) {
{
return true; return true;
} }
if(fc.getIsPrivate()) if (fc.getIsPrivate()) {
{ if (userUUID == null) {
if(userUUID == null)
{
return false; return false;
} }
UUID uUUID = UUID.fromString(userUUID); UUID uUUID = UUID.fromString(userUUID);
VipsLogicUser user = userBean.findVipsLogicUser(uUUID); VipsLogicUser user = userBean.findVipsLogicUser(uUUID);
if(user == null || ! user.getUserId().equals( fc.getVipsLogicUserId().getUserId())) if (user == null || !user.getUserId().equals(fc.getVipsLogicUserId().getUserId())) {
{
return false; return false;
} }
} }
return true; return true;
} }
public List<ForecastResult> getForecastResults(Long forecastConfigurationId, Integer latestDays) public List<ForecastResult> getForecastResults(Long forecastConfigurationId, Integer latestDays) {
{
ForecastResult mostRecentForecastResult = this.getMostRecentForecastResult(forecastConfigurationId); ForecastResult mostRecentForecastResult = this.getMostRecentForecastResult(forecastConfigurationId);
if(mostRecentForecastResult == null) if (mostRecentForecastResult == null) {
{
return null; return null;
} }
Calendar cal = Calendar.getInstance(); Calendar cal = Calendar.getInstance();
cal.setTime(mostRecentForecastResult.getValidTimeStart()); cal.setTime(mostRecentForecastResult.getValidTimeStart());
cal.add(Calendar.DATE, -latestDays); cal.add(Calendar.DATE, -latestDays);
Date startDate = cal.getTime(); Date startDate = cal.getTime();
return this.getForecastResults(forecastConfigurationId, startDate, mostRecentForecastResult.getValidTimeStart()); return this.getForecastResults(forecastConfigurationId, startDate,
mostRecentForecastResult.getValidTimeStart());
} }
public List<ForecastResult> getForecastResults(Long forecastConfigurationId, Date timeStart, Date timeEnd) public List<ForecastResult> getForecastResults(Long forecastConfigurationId, Date timeStart, Date timeEnd) {
{
Query q = em.createNamedQuery("ForecastResult.findByForecastConfigurationIdAndPeriod"); Query q = em.createNamedQuery("ForecastResult.findByForecastConfigurationIdAndPeriod");
q.setParameter("forecastConfigurationId", forecastConfigurationId); q.setParameter("forecastConfigurationId", forecastConfigurationId);
q.setParameter("timeStart", timeStart); q.setParameter("timeStart", timeStart);
q.setParameter("timeEnd", timeEnd); q.setParameter("timeEnd", timeEnd);
try try {
{
return q.getResultList(); return q.getResultList();
} } catch (NoResultException ex) {
catch(NoResultException ex)
{
return null; return null;
} }
} }
public ForecastResult getMostRecentForecastResult(Long forecastConfigurationId) public ForecastResult getMostRecentForecastResult(Long forecastConfigurationId) {
{
Query q = em.createNativeQuery( Query q = em.createNativeQuery(
"SELECT * FROM forecast_result " "SELECT * FROM forecast_result "
+ "WHERE forecast_configuration_id=:forecastConfigurationId " + "WHERE forecast_configuration_id=:forecastConfigurationId "
+ "AND valid_time_start = (" + "AND valid_time_start = ("
+ "SELECT MAX(valid_time_start) " + "SELECT MAX(valid_time_start) "
+ "FROM forecast_result " + "FROM forecast_result "
+ "WHERE forecast_configuration_id=:forecastConfigurationId " + "WHERE forecast_configuration_id=:forecastConfigurationId "
+ ");", ForecastResult.class); + ");",
ForecastResult.class);
q.setParameter("forecastConfigurationId", forecastConfigurationId); q.setParameter("forecastConfigurationId", forecastConfigurationId);
try try {
{
return (ForecastResult) q.getSingleResult(); return (ForecastResult) q.getSingleResult();
} } catch (NoResultException ex) {
catch(NoResultException ex)
{
return null; return null;
} }
} }
/** /**
* Deletes all former results for this forecast configuration, stores the new ones * Deletes all former results for this forecast configuration, stores the new ones
*
* @param forecastConfiguration * @param forecastConfiguration
* @param results * @param results
*/ */
public void storeResults(ForecastConfiguration forecastConfiguration, List<Result> results) public void storeResults(ForecastConfiguration forecastConfiguration, List<Result> results) {
{ // System.out.println("forecastConfigurationId=" + forecastConfiguration.getForecastConfigurationId());
//System.out.println("forecastConfigurationId=" + forecastConfiguration.getForecastConfigurationId()); Query q = em.createNativeQuery(
Query q = em.createNativeQuery("DELETE FROM public.forecast_result WHERE forecast_configuration_id=:forecastConfigurationId"); "DELETE FROM public.forecast_result WHERE forecast_configuration_id=:forecastConfigurationId");
q.setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId()); q.setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId());
q.executeUpdate(); q.executeUpdate();
for(Result result:results) for (Result result : results) {
{ ForecastResult fResult = new ForecastResult(forecastConfiguration.getForecastConfigurationId(), result);
ForecastResult fResult = new ForecastResult(forecastConfiguration.getForecastConfigurationId(),result);
em.persist(fResult); em.persist(fResult);
} }
} }
/** /**
* Get all PUBLIC forecast configurations for one user. * Get all PUBLIC forecast configurations for one user. TODO: Should be season based, or possibly based on
* TODO: Should be season based, or possibly based on start/stop date * start/stop date
*
* @param userId * @param userId
* @return * @return
*/ */
public List<ForecastConfiguration> getForecastConfigurationsForUser(Integer userId) public List<ForecastConfiguration> getForecastConfigurationsForUser(Integer userId) {
{
VipsLogicUser user = em.find(VipsLogicUser.class, userId); VipsLogicUser user = em.find(VipsLogicUser.class, userId);
Query q = em.createNamedQuery("ForecastConfiguration.findByVipsLogicUserId"); Query q = em.createNamedQuery("ForecastConfiguration.findByVipsLogicUserId");
q.setParameter("vipsLogicUserId", user); q.setParameter("vipsLogicUserId", user);
return q.getResultList(); return q.getResultList();
} }
/** /**
* Get all PRIVATE forecast configurations for one user. * Get all PRIVATE forecast configurations for one user. TODO: Should be season based, or possibly based on
* TODO: Should be season based, or possibly based on start/stop date * start/stop date
*
* @param userId * @param userId
* @return * @return
*/ */
public List<ForecastConfiguration> getPrivateForecastConfigurationsForUser(Integer userId) public List<ForecastConfiguration> getPrivateForecastConfigurationsForUser(Integer userId) {
{
VipsLogicUser user = em.find(VipsLogicUser.class, userId); VipsLogicUser user = em.find(VipsLogicUser.class, userId);
Query q = em.createNamedQuery("ForecastConfiguration.findPrivateByVipsLogicUserId"); Query q = em.createNamedQuery("ForecastConfiguration.findPrivateByVipsLogicUserId");
q.setParameter("vipsLogicUserId", user); q.setParameter("vipsLogicUserId", user);
return q.getResultList(); return q.getResultList();
} }
public List<ForecastConfiguration> getForecastConfigurationsForUserAndDate(Integer userId, Date from, Date to) {
public List<ForecastConfiguration> getForecastConfigurationsForUserAndDate(Integer userId, Date from, Date to)
{
VipsLogicUser user = em.find(VipsLogicUser.class, userId); VipsLogicUser user = em.find(VipsLogicUser.class, userId);
Query q = em.createNamedQuery("ForecastConfiguration.findByVipsLogicUserIdAndDate"); Query q = em.createNamedQuery("ForecastConfiguration.findByVipsLogicUserIdAndDate");
q.setParameter("vipsLogicUserId", user); q.setParameter("vipsLogicUserId", user);
...@@ -274,17 +256,18 @@ public class ForecastBean { ...@@ -274,17 +256,18 @@ public class ForecastBean {
q.setParameter("to", to); q.setParameter("to", to);
return q.getResultList(); return q.getResultList();
} }
public List<ForecastConfiguration> getForecastConfigurationsForUserAndCrops(Integer userId, List<Integer> cropOrganismIds) public List<ForecastConfiguration> getForecastConfigurationsForUserAndCrops(Integer userId,
{ List<Integer> cropOrganismIds) {
VipsLogicUser user = em.find(VipsLogicUser.class, userId); VipsLogicUser user = em.find(VipsLogicUser.class, userId);
Query q = em.createNamedQuery("ForecastConfiguration.findByVipsLogicUserIdAndCropOrganismId"); Query q = em.createNamedQuery("ForecastConfiguration.findByVipsLogicUserIdAndCropOrganismId");
q.setParameter("vipsLogicUserId", user); q.setParameter("vipsLogicUserId", user);
q.setParameter("cropOrganismIds", cropOrganismIds); q.setParameter("cropOrganismIds", cropOrganismIds);
return q.getResultList(); return q.getResultList();
} }
public List<ForecastConfiguration> getForecastConfigurationsForUserAndCropsAndDate(Integer userId, List<Integer> cropOrganismIds, Date from, Date to)
{ public List<ForecastConfiguration> getForecastConfigurationsForUserAndCropsAndDate(Integer userId,
List<Integer> cropOrganismIds, Date from, Date to) {
VipsLogicUser user = em.find(VipsLogicUser.class, userId); VipsLogicUser user = em.find(VipsLogicUser.class, userId);
Query q = em.createNamedQuery("ForecastConfiguration.findByVipsLogicUserIdAndCropOrganismIdsAndDate"); Query q = em.createNamedQuery("ForecastConfiguration.findByVipsLogicUserIdAndCropOrganismIdsAndDate");
q.setParameter("vipsLogicUserId", user); q.setParameter("vipsLogicUserId", user);
...@@ -293,30 +276,28 @@ public class ForecastBean { ...@@ -293,30 +276,28 @@ public class ForecastBean {
q.setParameter("to", to); q.setParameter("to", to);
return q.getResultList(); return q.getResultList();
} }
/** /**
* Returns _ALL_ forecasts. Not for the faint hearted * Returns _ALL_ forecasts. Not for the faint hearted
* @return *
* @return
*/ */
public List<ForecastConfiguration> getForecastConfigurations() public List<ForecastConfiguration> getForecastConfigurations() {
{
return em.createNamedQuery("ForecastConfiguration.findAll").getResultList(); return em.createNamedQuery("ForecastConfiguration.findAll").getResultList();
} }
/** /**
* *
* @return * @return
*/ */
public List<ForecastConfiguration> getForecastConfigurations(List<String> modelIds) public List<ForecastConfiguration> getForecastConfigurations(List<String> modelIds) {
{
return em.createNamedQuery("ForecastConfiguration.findByModelIds") return em.createNamedQuery("ForecastConfiguration.findByModelIds")
.setParameter("modelIds", modelIds) .setParameter("modelIds", modelIds)
.getResultList(); .getResultList();
} }
public List<ForecastConfiguration> getForecastConfigurations(Organization organization) public List<ForecastConfiguration> getForecastConfigurations(Organization organization) {
{
List<VipsLogicUser> organizationUsers = em List<VipsLogicUser> organizationUsers = em
.createNamedQuery("VipsLogicUser.findByOrganizationId") .createNamedQuery("VipsLogicUser.findByOrganizationId")
.setParameter("organizationId", organization) .setParameter("organizationId", organization)
...@@ -326,16 +307,15 @@ public class ForecastBean { ...@@ -326,16 +307,15 @@ public class ForecastBean {
.setParameter("vipsLogicUserIds", organizationUsers) .setParameter("vipsLogicUserIds", organizationUsers)
.getResultList(); .getResultList();
} }
public List<ForecastConfiguration> getForecastConfigurations(Organization organization, List<String> modelIds, Date from, Date to) public List<ForecastConfiguration> getForecastConfigurations(Organization organization, List<String> modelIds,
{ Date from, Date to) {
List<VipsLogicUser> organizationUsers = em List<VipsLogicUser> organizationUsers = em
.createNamedQuery("VipsLogicUser.findByOrganizationId") .createNamedQuery("VipsLogicUser.findByOrganizationId")
.setParameter("organizationId", organization) .setParameter("organizationId", organization)
.getResultList(); .getResultList();
if(!organizationUsers.isEmpty()) if (!organizationUsers.isEmpty()) {
{
return em return em
.createNamedQuery("ForecastConfiguration.findByVipsLogicUserIdsAndModelIdsAndDate") .createNamedQuery("ForecastConfiguration.findByVipsLogicUserIdsAndModelIdsAndDate")
.setParameter("vipsLogicUserIds", organizationUsers) .setParameter("vipsLogicUserIds", organizationUsers)
...@@ -343,22 +323,19 @@ public class ForecastBean { ...@@ -343,22 +323,19 @@ public class ForecastBean {
.setParameter("from", from) .setParameter("from", from)
.setParameter("to", to) .setParameter("to", to)
.getResultList(); .getResultList();
} } else {
else
{
return new ArrayList<>(); return new ArrayList<>();
} }
} }
public List<ForecastConfiguration> getForecastConfigurations(List<Integer> organizationIds, List<String> modelIds, Date from, Date to) public List<ForecastConfiguration> getForecastConfigurations(List<Integer> organizationIds, List<String> modelIds,
{ Date from, Date to) {
List<VipsLogicUser> organizationUsers = em List<VipsLogicUser> organizationUsers = em
.createNamedQuery("VipsLogicUser.findByOrganizationIds") .createNamedQuery("VipsLogicUser.findByOrganizationIds")
.setParameter("organizationIds", organizationIds) .setParameter("organizationIds", organizationIds)
.getResultList(); .getResultList();
if(!organizationUsers.isEmpty() && ! modelIds.isEmpty()) if (!organizationUsers.isEmpty() && !modelIds.isEmpty()) {
{
return em return em
.createNamedQuery("ForecastConfiguration.findByVipsLogicUserIdsAndModelIdsAndDate") .createNamedQuery("ForecastConfiguration.findByVipsLogicUserIdsAndModelIdsAndDate")
.setParameter("vipsLogicUserIds", organizationUsers) .setParameter("vipsLogicUserIds", organizationUsers)
...@@ -366,117 +343,109 @@ public class ForecastBean { ...@@ -366,117 +343,109 @@ public class ForecastBean {
.setParameter("from", from) .setParameter("from", from)
.setParameter("to", to) .setParameter("to", to)
.getResultList(); .getResultList();
} } else {
else
{
return new ArrayList<>(); return new ArrayList<>();
} }
} }
public List<ForecastConfiguration> getForecastConfigurations(List<Integer> organizationIds, Date from, Date to) public List<ForecastConfiguration> getForecastConfigurations(List<Integer> organizationIds, Date from, Date to) {
{
List<VipsLogicUser> organizationUsers = em List<VipsLogicUser> organizationUsers = em
.createNamedQuery("VipsLogicUser.findByOrganizationIds") .createNamedQuery("VipsLogicUser.findByOrganizationIds")
.setParameter("organizationIds", organizationIds) .setParameter("organizationIds", organizationIds)
.getResultList(); .getResultList();
if(!organizationUsers.isEmpty()) if (!organizationUsers.isEmpty()) {
{
return em return em
.createNamedQuery("ForecastConfiguration.findByVipsLogicUserIdsAndDate") .createNamedQuery("ForecastConfiguration.findByVipsLogicUserIdsAndDate")
.setParameter("vipsLogicUserIds", organizationUsers) .setParameter("vipsLogicUserIds", organizationUsers)
.setParameter("from", from) .setParameter("from", from)
.setParameter("to", to) .setParameter("to", to)
.getResultList(); .getResultList();
} } else {
else
{
return new ArrayList<>(); return new ArrayList<>();
} }
} }
public List<ForecastConfiguration> getForecastConfigurationsByWeatherStation(PointOfInterestWeatherStation weatherStation) public List<ForecastConfiguration> getForecastConfigurationsByWeatherStation(
{ PointOfInterestWeatherStation weatherStation) {
return em return em
.createNamedQuery("ForecastConfiguration.findByWeatherStationPointOfInterestId", ForecastConfiguration.class) .createNamedQuery("ForecastConfiguration.findByWeatherStationPointOfInterestId",
ForecastConfiguration.class)
.setParameter("weatherStationPointOfInterestId", weatherStation) .setParameter("weatherStationPointOfInterestId", weatherStation)
.getResultList(); .getResultList();
} }
public List<ForecastConfiguration> getForecastConfigurationsByLocation(PointOfInterest poi) public List<ForecastConfiguration> getForecastConfigurationsByLocation(PointOfInterest poi) {
{
return em return em
.createNamedQuery("ForecastConfiguration.findByLocationPointOfInterestId", ForecastConfiguration.class) .createNamedQuery("ForecastConfiguration.findByLocationPointOfInterestId", ForecastConfiguration.class)
.setParameter("locationPointOfInterestId", poi) .setParameter("locationPointOfInterestId", poi)
.getResultList(); .getResultList();
} }
public List<ForecastConfiguration> getForecastConfigurations(PointOfInterestWeatherStation weatherStation,Date from, Date to) public List<ForecastConfiguration> getForecastConfigurations(PointOfInterestWeatherStation weatherStation,
{ Date from, Date to) {
return em return em
.createNamedQuery("ForecastConfiguration.findByWeatherStationPointOfInterestIdAndDate", ForecastConfiguration.class) .createNamedQuery("ForecastConfiguration.findByWeatherStationPointOfInterestIdAndDate",
ForecastConfiguration.class)
.setParameter("weatherStationPointOfInterestId", weatherStation) .setParameter("weatherStationPointOfInterestId", weatherStation)
.setParameter("from", from) .setParameter("from", from)
.setParameter("to", to) .setParameter("to", to)
.getResultList(); .getResultList();
} }
/** /**
* Deletes all forecasts and results from the given weather station * Deletes all forecasts and results from the given weather station
* @param weatherStation *
* @param weatherStation
*/ */
public void deleteForecastConfigurationsForWeatherStation(PointOfInterestWeatherStation weatherStation) public void deleteForecastConfigurationsForWeatherStation(PointOfInterestWeatherStation weatherStation) {
{ List<ForecastConfiguration> forecastConfigurations =
List<ForecastConfiguration> forecastConfigurations = this.getForecastConfigurationsByWeatherStation(weatherStation); this.getForecastConfigurationsByWeatherStation(weatherStation);
for(ForecastConfiguration forecastConfiguration:forecastConfigurations) for (ForecastConfiguration forecastConfiguration : forecastConfigurations) {
{
em.createNativeQuery("DELETE FROM forecast_result WHERE forecast_configuration_id=:forecastConfigurationId") em.createNativeQuery("DELETE FROM forecast_result WHERE forecast_configuration_id=:forecastConfigurationId")
.setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId()) .setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId())
.executeUpdate(); .executeUpdate();
em.remove(forecastConfiguration); em.remove(forecastConfiguration);
} }
} }
/** /**
* Deletes all forecasts and results from the given location * Deletes all forecasts and results from the given location
* @param weatherStation *
* @param weatherStation
*/ */
public void deleteForecastConfigurationsForLocation(PointOfInterest location) public void deleteForecastConfigurationsForLocation(PointOfInterest location) {
{
List<ForecastConfiguration> forecastConfigurations = this.getForecastConfigurationsByLocation(location); List<ForecastConfiguration> forecastConfigurations = this.getForecastConfigurationsByLocation(location);
for(ForecastConfiguration forecastConfiguration:forecastConfigurations) for (ForecastConfiguration forecastConfiguration : forecastConfigurations) {
{
em.createNativeQuery("DELETE FROM forecast_result WHERE forecast_configuration_id=:forecastConfigurationId") em.createNativeQuery("DELETE FROM forecast_result WHERE forecast_configuration_id=:forecastConfigurationId")
.setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId()) .setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId())
.executeUpdate(); .executeUpdate();
em.remove(forecastConfiguration); em.remove(forecastConfiguration);
} }
} }
/** /**
* Fetches one specific forecast configuration * Fetches one specific forecast configuration
*
* @param forecastConfigurationId * @param forecastConfigurationId
* @return * @return
*/ */
public ForecastConfiguration getForecastConfiguration(Long forecastConfigurationId) public ForecastConfiguration getForecastConfiguration(Long forecastConfigurationId) {
{
return em.find(ForecastConfiguration.class, forecastConfigurationId); return em.find(ForecastConfiguration.class, forecastConfigurationId);
} }
/** /**
* Requests all info about models currently available in VIPSCoreManager * Requests all info about models currently available in VIPSCoreManager Stores in local db for easy access.
* Stores in local db for easy access.
*/ */
public TaskResult updateModelInformation() public TaskResult updateModelInformation() {
{
TaskResult taskResult = new TaskResult(); TaskResult taskResult = new TaskResult();
String jobReport = ""; String jobReport = "";
// Iterate all the VIPSCore instances // Iterate all the VIPSCore instances
List<VipsCoreInstance> vipsCoreInstances = em.createNamedQuery("VipsCoreInstance.findAll").getResultList(); List<VipsCoreInstance> vipsCoreInstances = em.createNamedQuery("VipsCoreInstance.findAll").getResultList();
Integer instancesCompleted = 0; Integer instancesCompleted = 0;
for(VipsCoreInstance vipsCoreInstance:vipsCoreInstances) { for (VipsCoreInstance vipsCoreInstance : vipsCoreInstances) {
LOGGER.debug("Attempting to connect to " + vipsCoreInstance.getUri() ); LOGGER.debug("Attempting to connect to " + vipsCoreInstance.getUri());
try { try {
Client client = ClientBuilder.newClient(); Client client = ClientBuilder.newClient();
WebTarget target = client.target(vipsCoreInstance.getUri()); WebTarget target = client.target(vipsCoreInstance.getUri());
...@@ -486,8 +455,9 @@ public class ForecastBean { ...@@ -486,8 +455,9 @@ public class ForecastBean {
// Get all model Ids from Core Manager // Get all model Ids from Core Manager
Response resp = resource.printModelListJSON(); Response resp = resource.printModelListJSON();
LOGGER.debug(vipsCoreInstance.getUri() + " returned status code " + String.valueOf(resp.getStatus())); LOGGER.debug(vipsCoreInstance.getUri() + " returned status code " + String.valueOf(resp.getStatus()));
if(resp.getStatus() != 200) { if (resp.getStatus() != 200) {
jobReport += vipsCoreInstance.getUri() + " returned status code " + String.valueOf(resp.getStatus()) + "\n"; jobReport += vipsCoreInstance.getUri() + " returned status code " + String.valueOf(resp.getStatus())
+ "\n";
continue; continue;
} }
...@@ -509,36 +479,34 @@ public class ForecastBean { ...@@ -509,36 +479,34 @@ public class ForecastBean {
// Retrieve and store information // Retrieve and store information
Response r = resource.printModelName(modelId); Response r = resource.printModelName(modelId);
modelInformation.setDefaultName(r.readEntity(String.class)); modelInformation.setDefaultName(r.readEntity(String.class));
//r.close(); // r.close();
r = resource.printModelDescription(modelId); r = resource.printModelDescription(modelId);
modelInformation.setDefaultDescription(r.readEntity(String.class)); modelInformation.setDefaultDescription(r.readEntity(String.class));
//r.close(); // r.close();
r = resource.printModelLicense(modelId); r = resource.printModelLicense(modelId);
modelInformation.setLicense(r.readEntity(String.class)); modelInformation.setLicense(r.readEntity(String.class));
//r.close(); // r.close();
r = resource.printModelCopyright(modelId); r = resource.printModelCopyright(modelId);
modelInformation.setCopyrightHolder(r.readEntity(String.class)); modelInformation.setCopyrightHolder(r.readEntity(String.class));
//r.close(); // r.close();
r = resource.printModelUsage(modelId); r = resource.printModelUsage(modelId);
modelInformation.setUsage(r.readEntity(String.class)); modelInformation.setUsage(r.readEntity(String.class));
//r.close(); // r.close();
r = resource.printModelSampleConfig(modelId); r = resource.printModelSampleConfig(modelId);
modelInformation.setSampleConfig(r.readEntity(String.class)); modelInformation.setSampleConfig(r.readEntity(String.class));
//r.close(); // r.close();
modelInformation.setDateLastRegistered(new Date()); modelInformation.setDateLastRegistered(new Date());
} }
resp.close(); resp.close();
client.close(); client.close();
instancesCompleted++; instancesCompleted++;
} } catch (ProcessingException ex) {
catch(ProcessingException ex)
{
jobReport += ex.getMessage() + "\n"; jobReport += ex.getMessage() + "\n";
} }
...@@ -547,263 +515,261 @@ public class ForecastBean { ...@@ -547,263 +515,261 @@ public class ForecastBean {
taskResult.setMessage(jobReport); taskResult.setMessage(jobReport);
return taskResult; return taskResult;
} }
/** /**
* *
* @return All registered models accessible by ModelId as key * @return All registered models accessible by ModelId as key
*/ */
public Map<String,ModelInformation> getIndexedModelInformation() public Map<String, ModelInformation> getIndexedModelInformation() {
{
Map<String, ModelInformation> retVal = new HashMap<>(); Map<String, ModelInformation> retVal = new HashMap<>();
for(ModelInformation mi: (List<ModelInformation>) em.createNamedQuery("ModelInformation.findAll").getResultList()) for (ModelInformation mi : (List<ModelInformation>) em.createNamedQuery("ModelInformation.findAll")
{ .getResultList()) {
retVal.put(mi.getModelId(), mi); retVal.put(mi.getModelId(), mi);
} }
return retVal; return retVal;
} }
/** /**
* *
* @return All registered models that has its own preprocessor accessible by ModelId as key * @return All registered models that has its own preprocessor accessible by ModelId as key
*/ */
public Map<String,ModelInformation> getIndexedBatchableModelInformation() public Map<String, ModelInformation> getIndexedBatchableModelInformation() {
{
Map<String, ModelInformation> retVal = new HashMap<>(); Map<String, ModelInformation> retVal = new HashMap<>();
this.getBatchableModels().forEach((mi) -> { this.getBatchableModels().forEach((mi) -> {
retVal.put(mi.getModelId(), mi); retVal.put(mi.getModelId(), mi);
}); });
return retVal; return retVal;
} }
public ModelInformation getModelInformation(String modelId) public ModelInformation getModelInformation(String modelId) {
{ try {
try return em.createNamedQuery("ModelInformation.findByModelId", ModelInformation.class)
{ .setParameter("modelId", modelId).getSingleResult();
return em.createNamedQuery("ModelInformation.findByModelId", ModelInformation.class).setParameter("modelId", modelId).getSingleResult(); } catch (NoResultException ex) {
}
catch(NoResultException ex)
{
return null; return null;
} }
} }
/** /**
* Stores a forecast configuration, including model specific form fields * Stores a forecast configuration, including model specific form fields
*
* @param forecastConfiguration * @param forecastConfiguration
* @param formFields * @param formFields
* @param modelSpecificFormFields * @param modelSpecificFormFields
* @return the updated (or freshly created, with brand new Id) forecast configuration * @return the updated (or freshly created, with brand new Id) forecast configuration
*/ */
public ForecastConfiguration storeForecastConfiguration(ForecastConfiguration forecastConfiguration, Map<String, FormField> formFields, Map<String, FormField> modelSpecificFormFields) public ForecastConfiguration storeForecastConfiguration(ForecastConfiguration forecastConfiguration,
{ Map<String, FormField> formFields, Map<String, FormField> modelSpecificFormFields) {
forecastConfiguration.setModelId(formFields.get("modelId").getWebValue()); forecastConfiguration.setModelId(formFields.get("modelId").getWebValue());
forecastConfiguration.setCropOrganismId(em.find(Organism.class, formFields.get("cropOrganismId").getValueAsInteger())); forecastConfiguration
forecastConfiguration.setPestOrganismId(em.find(Organism.class, formFields.get("pestOrganismId").getValueAsInteger())); .setCropOrganismId(em.find(Organism.class, formFields.get("cropOrganismId").getValueAsInteger()));
forecastConfiguration
.setPestOrganismId(em.find(Organism.class, formFields.get("pestOrganismId").getValueAsInteger()));
forecastConfiguration.setIsPrivate(formFields.get("isPrivate").getWebValue() != null); forecastConfiguration.setIsPrivate(formFields.get("isPrivate").getWebValue() != null);
PointOfInterest locationPoi = em.find(PointOfInterest.class, formFields.get("locationPointOfInterestId").getValueAsInteger()); forecastConfiguration.setUseGridWeatherData(formFields.get("useGridWeatherData").getWebValue() != null
&& formFields.get("useGridWeatherData").getWebValue().equals("true"));
PointOfInterest locationPoi =
em.find(PointOfInterest.class, formFields.get("locationPointOfInterestId").getValueAsInteger());
forecastConfiguration.setLocationPointOfInterestId(locationPoi); forecastConfiguration.setLocationPointOfInterestId(locationPoi);
PointOfInterest weatherStationPoi = em.find(PointOfInterestWeatherStation.class, formFields.get("weatherStationPointOfInterestId").getValueAsInteger()); PointOfInterest weatherStationPoi = em.find(PointOfInterestWeatherStation.class,
formFields.get("weatherStationPointOfInterestId").getValueAsInteger());
forecastConfiguration.setWeatherStationPointOfInterestId(weatherStationPoi); forecastConfiguration.setWeatherStationPointOfInterestId(weatherStationPoi);
String timeZone = formFields.get("timeZone").getWebValue(); String timeZone = formFields.get("timeZone").getWebValue();
forecastConfiguration.setTimeZone(timeZone); forecastConfiguration.setTimeZone(timeZone);
forecastConfiguration.setDateStart(formFields.get("dateStart").getValueAsDate()); forecastConfiguration.setDateStart(formFields.get("dateStart").getValueAsDate());
forecastConfiguration.setDateEnd(formFields.get("dateEnd").getValueAsDate()); forecastConfiguration.setDateEnd(formFields.get("dateEnd").getValueAsDate());
VipsLogicUser forecastConfigurationUser = em.find(VipsLogicUser.class, formFields.get("vipsLogicUserId").getValueAsInteger()); VipsLogicUser forecastConfigurationUser =
em.find(VipsLogicUser.class, formFields.get("vipsLogicUserId").getValueAsInteger());
forecastConfiguration.setVipsCoreUserId(forecastConfigurationUser); forecastConfiguration.setVipsCoreUserId(forecastConfigurationUser);
forecastConfiguration = em.merge(forecastConfiguration); forecastConfiguration = em.merge(forecastConfiguration);
// Reset all model configurations, then store the new ones // Reset all model configurations, then store the new ones
// As for now: We keep the old ones. // As for now: We keep the old ones.
// Reason: If anybody screws up by changing a form, old configurations could get lost // Reason: If anybody screws up by changing a form, old configurations could get lost
/*List<ForecastModelConfiguration> configsToRemove = em.createNamedQuery("ForecastModelConfiguration.findByForecastConfigurationId").setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId()).getResultList(); /*
for(ForecastModelConfiguration configToRemove: configsToRemove) * List<ForecastModelConfiguration> configsToRemove =
{ * em.createNamedQuery("ForecastModelConfiguration.findByForecastConfigurationId").setParameter(
em.remove(configToRemove); * "forecastConfigurationId", forecastConfiguration.getForecastConfigurationId()).getResultList();
} * for(ForecastModelConfiguration configToRemove: configsToRemove) { em.remove(configToRemove); } em.flush();
em.flush();*/ */
// Store new values // Store new values
for(FormField field : modelSpecificFormFields.values()) for (FormField field : modelSpecificFormFields.values()) {
{
String deCamelizedFieldName = getDeCamelizedFieldName(forecastConfiguration.getModelId(), field.getName()); String deCamelizedFieldName = getDeCamelizedFieldName(forecastConfiguration.getModelId(), field.getName());
ForecastModelConfiguration forecastModelConfiguration = new ForecastModelConfiguration(forecastConfiguration.getForecastConfigurationId(), deCamelizedFieldName); ForecastModelConfiguration forecastModelConfiguration = new ForecastModelConfiguration(
forecastConfiguration.getForecastConfigurationId(), deCamelizedFieldName);
forecastModelConfiguration.setParameterValue(field.getWebValue()); forecastModelConfiguration.setParameterValue(field.getWebValue());
em.merge(forecastModelConfiguration); em.merge(forecastModelConfiguration);
} }
return forecastConfiguration; return forecastConfiguration;
} }
/** /**
* *
* @param modelId * @param modelId
* @param camelCaseName * @param camelCaseName
* @return MODELID_CAMEL_CASE_NAME * @return MODELID_CAMEL_CASE_NAME
*/ */
public String getDeCamelizedFieldName(String modelId, String camelCaseName) public String getDeCamelizedFieldName(String modelId, String camelCaseName) {
{
StringBuilder deCamelizedFieldName = new StringBuilder(modelId.toUpperCase()); StringBuilder deCamelizedFieldName = new StringBuilder(modelId.toUpperCase());
for(String phrase : camelCaseName.split("(?=\\p{Lu})")) for (String phrase : camelCaseName.split("(?=\\p{Lu})")) {
{
deCamelizedFieldName.append("_").append(phrase.toUpperCase()); deCamelizedFieldName.append("_").append(phrase.toUpperCase());
} }
return deCamelizedFieldName.toString(); return deCamelizedFieldName.toString();
} }
public List<ForecastModelConfiguration> getForecastModelConfigurations(Long forecastConfigurationId) public List<ForecastModelConfiguration> getForecastModelConfigurations(Long forecastConfigurationId) {
{ return em.createNamedQuery("ForecastModelConfiguration.findByForecastConfigurationId")
return em.createNamedQuery("ForecastModelConfiguration.findByForecastConfigurationId").setParameter("forecastConfigurationId", forecastConfigurationId).getResultList(); .setParameter("forecastConfigurationId", forecastConfigurationId).getResultList();
} }
/** /**
* Deletes a forecast configuration and all results * Deletes a forecast configuration and all results
* @param forecastConfigurationId *
* @param forecastConfigurationId
*/ */
public void deleteForecastConfiguration(Long forecastConfigurationId) public void deleteForecastConfiguration(Long forecastConfigurationId) {
{
// The entity relationship between ForecastConfiguration and ForecastResult // The entity relationship between ForecastConfiguration and ForecastResult
// is not explicit in EJB model, but in the database there is a foreign key // is not explicit in EJB model, but in the database there is a foreign key
// in forecast_result (and in forecast summary) referencing the forecast_configuration // in forecast_result (and in forecast summary) referencing the forecast_configuration
// Explicit deletion of forecast_results rows is therefore necessary. // Explicit deletion of forecast_results rows is therefore necessary.
ForecastConfiguration forecastConfiguration = em.find(ForecastConfiguration.class, forecastConfigurationId); ForecastConfiguration forecastConfiguration = em.find(ForecastConfiguration.class, forecastConfigurationId);
Query q = em.createNativeQuery("DELETE FROM public.forecast_result WHERE forecast_configuration_id=:forecastConfigurationId"); Query q = em.createNativeQuery(
"DELETE FROM public.forecast_result WHERE forecast_configuration_id=:forecastConfigurationId");
q.setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId()); q.setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId());
q.executeUpdate(); q.executeUpdate();
q = em.createNativeQuery("DELETE FROM public.forecast_summary WHERE forecast_configuration_id=:forecastConfigurationId"); q = em.createNativeQuery(
"DELETE FROM public.forecast_summary WHERE forecast_configuration_id=:forecastConfigurationId");
q.setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId());
q.executeUpdate();
// Entries in ForecastNotificationLog referencing the ForecastConfiguration must also be deleted
q = em.createNativeQuery(
"DELETE FROM messaging.forecast_notification_log WHERE forecast_configuration_id=:forecastConfigurationId");
q.setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId()); q.setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId());
q.executeUpdate(); q.executeUpdate();
em.remove(forecastConfiguration); em.remove(forecastConfiguration);
} }
public List<ForecastConfiguration> getForecastConfigurationsValidAtTime(Organization organization, Date time) public List<ForecastConfiguration> getForecastConfigurationsValidAtTime(Organization organization, Date time) {
{
Query q = em.createNativeQuery( Query q = em.createNativeQuery(
"SELECT * FROM public.forecast_configuration " "SELECT * FROM public.forecast_configuration "
+ "WHERE vips_logic_user_id IN (SELECT user_id FROM public.vips_logic_user WHERE organization_id=:organizationId) " + "WHERE vips_logic_user_id IN (SELECT user_id FROM public.vips_logic_user WHERE organization_id=:organizationId) "
+ "AND :time BETWEEN date_start AND date_end " + "AND :time BETWEEN date_start AND date_end "
+ "ORDER BY weather_station_point_of_interest_id ASC " + "ORDER BY weather_station_point_of_interest_id ASC ",
,ForecastConfiguration.class); ForecastConfiguration.class);
q.setParameter("organizationId", organization.getOrganizationId()); q.setParameter("organizationId", organization.getOrganizationId());
q.setParameter("time", time); q.setParameter("time", time);
return q.getResultList(); return q.getResultList();
} }
public void runForecast(ForecastConfiguration forecastConfiguration) throws PreprocessorException, RunModelException public void runForecast(ForecastConfiguration forecastConfiguration)
{ throws PreprocessorException, RunModelException {
ModelRunPreprocessor preprocessor = ModelRunPreprocessorFactory.getModelRunPreprocessor(forecastConfiguration.getModelId()); ModelRunPreprocessor preprocessor =
if(preprocessor != null) ModelRunPreprocessorFactory.getModelRunPreprocessor(forecastConfiguration.getModelId());
{ if (preprocessor != null) {
ModelConfiguration config = preprocessor.getModelConfiguration(forecastConfiguration); ModelConfiguration config = preprocessor.getModelConfiguration(forecastConfiguration);
ModelRunRequest request = new ModelRunRequest(config); ModelRunRequest request = new ModelRunRequest(config);
Map<String,String> loginInfo = new HashMap<>(); Map<String, String> loginInfo = new HashMap<>();
// VIPSLogic logs in on behalf of client // VIPSLogic logs in on behalf of client
ModelInformation modelInformation = em.find(ModelInformation.class, config.getModelId()); ModelInformation modelInformation = em.find(ModelInformation.class, config.getModelId());
if(modelInformation.getVipsCoreInstanceId() == null) if (modelInformation.getVipsCoreInstanceId() == null) {
{ throw new RunModelException(
throw new RunModelException("ERROR: Model " + modelInformation.getDefaultName() + "(" + config.getModelId() + ") is not connected to a VIPSCoreInstance. Please check your server configuration."); "ERROR: Model " + modelInformation.getDefaultName() + "(" + config.getModelId()
} + ") is not connected to a VIPSCoreInstance. Please check your server configuration.");
loginInfo.put("username",modelInformation.getVipsCoreInstanceId().getUsername()); }
//loginInfo.put("username","wrongusername"); loginInfo.put("username", modelInformation.getVipsCoreInstanceId().getUsername());
loginInfo.put("password",modelInformation.getVipsCoreInstanceId().getPassword()); // loginInfo.put("username","wrongusername");
request.setLoginInfo(loginInfo); loginInfo.put("password", modelInformation.getVipsCoreInstanceId().getPassword());
// We tell which client this is (the db Id in VIPSCoreManager) request.setLoginInfo(loginInfo);
Integer VIPSCoreUserId = forecastConfiguration.getVipsLogicUserId().getVipsCoreUserIdWithFallback(); // We tell which client this is (the db Id in VIPSCoreManager)
if(VIPSCoreUserId == null) Integer VIPSCoreUserId = forecastConfiguration.getVipsLogicUserId().getVipsCoreUserIdWithFallback();
{ if (VIPSCoreUserId == null) {
throw new PreprocessorException("No user id found for forecast #" + forecastConfiguration.getForecastConfigurationId() + throw new PreprocessorException(
". Possible reason: The user's organization (" "No user id found for forecast #" + forecastConfiguration.getForecastConfigurationId() +
+ forecastConfiguration.getVipsLogicUserId().getOrganizationId().getOrganizationName() ". Possible reason: The user's organization ("
+ ") hasn't got a VIPSCoreUserId."); + forecastConfiguration.getVipsLogicUserId().getOrganizationId().getOrganizationName()
} + ") hasn't got a VIPSCoreUserId.");
//System.out.println("VIPSCoreUserId = " + VIPSCoreUserId + ", name=" + forecastConfiguration.getVipsLogicUserId().getLastName()); }
request.setVipsCoreUserId(VIPSCoreUserId); // System.out.println("VIPSCoreUserId = " + VIPSCoreUserId + ", name=" +
//System.out.println("RunModel for wsId " + forecastConfiguration.getWeatherStationPointOfInterestId()); // forecastConfiguration.getVipsLogicUserId().getLastName());
//System.out.println(config.toJSON()); request.setVipsCoreUserId(VIPSCoreUserId);
/* DEBUG STUFF */ // System.out.println("RunModel for wsId " + forecastConfiguration.getWeatherStationPointOfInterestId());
/*ObjectMapper mapper = new ObjectMapper(); // System.out.println(config.toJSON());
try /* DEBUG STUFF */
{ /*
System.out.println(mapper.writeValueAsString(request)); * ObjectMapper mapper = new ObjectMapper(); try { System.out.println(mapper.writeValueAsString(request)); }
} * catch(JsonProcessingException ex) { ex.printStackTrace(); }
catch(JsonProcessingException ex) */
{
ex.printStackTrace(); Response resp = this.getManagerResource(modelInformation).runModel(config.getModelId(), request);
}*/ if (resp.getStatus() == Response.Status.OK.getStatusCode()) {
// System.out.println(resp.readEntity(String.class));
Response resp = this.getManagerResource(modelInformation).runModel(config.getModelId(), request); List<Result> results = (List<Result>) resp.readEntity(new GenericType<List<Result>>() {});
if(resp.getStatus() == Response.Status.OK.getStatusCode()) // System.out.println("ForecastConfigId=" + forecastConfiguration.getForecastConfigurationId() + ",
{ // resultsize=" + results.size());
//System.out.println(resp.readEntity(String.class)); // We delete all former results before we store the new ones
List<Result> results = (List<Result>) resp.readEntity(new GenericType<List<Result>>(){}); forecastBean.storeResults(forecastConfiguration, results);
//System.out.println("ForecastConfigId=" + forecastConfiguration.getForecastConfigurationId() + ", resultsize=" + results.size()); } else {
// We delete all former results before we store the new ones throw new RunModelException(resp.readEntity(String.class));
forecastBean.storeResults(forecastConfiguration,results); }
} // System.out.println("Finished runModel for wsId" +
else // forecastConfiguration.getWeatherStationPointOfInterestId());
{
throw new RunModelException(resp.readEntity(String.class)); } else {
} throw new PreprocessorException(
//System.out.println("Finished runModel for wsId" + forecastConfiguration.getWeatherStationPointOfInterestId()); "Could not find model with id=|" + forecastConfiguration.getModelId() + "|");
}
else
{
throw new PreprocessorException("Could not find model with id=|" + forecastConfiguration.getModelId() + "|");
} }
} }
public List<Result> runForecast(ModelConfiguration config, Integer VIPSCoreUserId) throws RunModelException public List<Result> runForecast(ModelConfiguration config, Integer VIPSCoreUserId) throws RunModelException {
{
ModelInformation modelInformation = em.find(ModelInformation.class, config.getModelId()); ModelInformation modelInformation = em.find(ModelInformation.class, config.getModelId());
if(modelInformation.getVipsCoreInstanceId() == null) if (modelInformation.getVipsCoreInstanceId() == null) {
{ throw new RunModelException("ERROR: Model " + modelInformation.getDefaultName() + "(" + config.getModelId()
throw new RunModelException("ERROR: Model " + modelInformation.getDefaultName() + "(" + config.getModelId() + ") is not connected to a VIPSCoreInstance. Please check your server configuration."); + ") is not connected to a VIPSCoreInstance. Please check your server configuration.");
} }
ModelRunRequest request = new ModelRunRequest(config); ModelRunRequest request = new ModelRunRequest(config);
Map<String,String> loginInfo = new HashMap<>(); Map<String, String> loginInfo = new HashMap<>();
// VIPSLogic logs in on behalf of client // VIPSLogic logs in on behalf of client
loginInfo.put("username",modelInformation.getVipsCoreInstanceId().getUsername()); loginInfo.put("username", modelInformation.getVipsCoreInstanceId().getUsername());
//loginInfo.put("username","wrongusername"); // loginInfo.put("username","wrongusername");
loginInfo.put("password",modelInformation.getVipsCoreInstanceId().getPassword()); loginInfo.put("password", modelInformation.getVipsCoreInstanceId().getPassword());
request.setLoginInfo(loginInfo); request.setLoginInfo(loginInfo);
//System.out.println("VIPSCoreUserId = " + VIPSCoreUserId + ", name=" + forecastConfiguration.getVipsLogicUserId().getLastName()); // System.out.println("VIPSCoreUserId = " + VIPSCoreUserId + ", name=" +
// forecastConfiguration.getVipsLogicUserId().getLastName());
request.setVipsCoreUserId(VIPSCoreUserId); request.setVipsCoreUserId(VIPSCoreUserId);
//System.out.println("RunModel for wsId" + forecastConfiguration.getWeatherStationPointOfInterestId()); // System.out.println("RunModel for wsId" + forecastConfiguration.getWeatherStationPointOfInterestId());
Response resp = this.getManagerResource(modelInformation).runModel(config.getModelId(), request); Response resp = this.getManagerResource(modelInformation).runModel(config.getModelId(), request);
if(resp.getStatus() == Response.Status.OK.getStatusCode()) if (resp.getStatus() == Response.Status.OK.getStatusCode()) {
{ return resp.readEntity(new GenericType<>() {});
List<Result> results = (List<Result>) resp.readEntity(new GenericType<List<Result>>(){}); } else {
return results;
}
else
{
throw new RunModelException(resp.readEntity(String.class)); throw new RunModelException(resp.readEntity(String.class));
} }
} }
/** /**
* Get the interface for REST resources in VIPSCoreManager * Get the interface for REST resources in VIPSCoreManager
* @return *
* @return
*/ */
private ManagerResource getManagerResource(ModelInformation modelInformation) private ManagerResource getManagerResource(ModelInformation modelInformation) {
{
Client client = ClientBuilder.newClient(); Client client = ClientBuilder.newClient();
WebTarget target = client.target(modelInformation.getVipsCoreInstanceId().getUri()); WebTarget target = client.target(modelInformation.getVipsCoreInstanceId().getUri());
ResteasyWebTarget rTarget = (ResteasyWebTarget) target; ResteasyWebTarget rTarget = (ResteasyWebTarget) target;
ManagerResource resource = rTarget.proxy(ManagerResource.class); ManagerResource resource = rTarget.proxy(ManagerResource.class);
return resource; return resource;
} }
public Kml getForecastsAggregateKml(List<Integer> organizationIds, List<Integer> cropOrganismIds, Date theDate, String serverName, VipsLogicUser user) public Kml getForecastsAggregateKml(List<Integer> organizationIds, List<Integer> cropOrganismIds, Date theDate,
{ String serverName, VipsLogicUser user) {
//String iconPath = Globals.PROTOCOL + "://" + serverName + "/public/images/"; // String iconPath = Globals.PROTOCOL + "://" + serverName + "/public/images/";
//String iconPath = "//" + serverName + "/public/images/"; // String iconPath = "//" + serverName + "/public/images/";
String iconPath = "https://logic.vips.nibio.no/public/images/"; String iconPath = "https://logic.vips.nibio.no/public/images/";
// Initialization // Initialization
final Vec2 hotspot = new Vec2() final Vec2 hotspot = new Vec2()
...@@ -813,66 +779,60 @@ public class ForecastBean { ...@@ -813,66 +779,60 @@ public class ForecastBean {
.withYunits(Units.FRACTION); .withYunits(Units.FRACTION);
final Kml kml = KmlFactory.createKml(); final Kml kml = KmlFactory.createKml();
final Document document = kml.createAndSetDocument() final Document document = kml.createAndSetDocument()
.withName("Forecast results - aggregates").withDescription("Worst forecasts for each POI"); .withName("Forecast results - aggregates").withDescription("Worst forecasts for each POI");
LabelStyle noLabel = new LabelStyle().withScale(0.0); LabelStyle noLabel = new LabelStyle().withScale(0.0);
Calendar cal = Calendar.getInstance(); Calendar cal = Calendar.getInstance();
cal.setTime(SystemTime.getSystemTime()); cal.setTime(SystemTime.getSystemTime());
for(int i=0;i<=4;i++) for (int i = 0; i <= 4; i++) {
{
document.createAndAddStyle() document.createAndAddStyle()
.withId("warning_type_" + i) .withId("warning_type_" + i)
.withLabelStyle(noLabel) .withLabelStyle(noLabel)
.createAndSetIconStyle() .createAndSetIconStyle()
.withScale(1) .withScale(1)
.withHotSpot(hotspot) .withHotSpot(hotspot)
.createAndSetIcon() .createAndSetIcon()
.withHref(iconPath + "station_icon_status_" + .withHref(iconPath + "station_icon_status_" +
(cal.get(Calendar.MONTH) <= 1 ? "winter" : (cal.get(Calendar.MONTH) <= 1 ? "winter"
cal.get(Calendar.MONTH) == Calendar.DECEMBER ? "xmas" : i) : cal.get(Calendar.MONTH) == Calendar.DECEMBER ? "xmas" : i)
+ ".png"); + ".png");
} }
// Run through forecast configurations // Run through forecast configurations
//Date benchmark = new Date(); // Date benchmark = new Date();
List<PointOfInterest> poisWithAggregate = new ArrayList<>(); List<PointOfInterest> poisWithAggregate = new ArrayList<>();
if(organizationIds.size() == 1 && organizationIds.get(0).equals(-1)) if (organizationIds.size() == 1 && organizationIds.get(0).equals(-1)) {
{ em.createNamedQuery("Organization.findAll", Organization.class).getResultStream().forEach(
em.createNamedQuery("Organization.findAll",Organization.class).getResultStream().forEach( org -> poisWithAggregate.addAll(getPointOfInterestForecastsAggregate(org.getOrganizationId(),
org-> poisWithAggregate.addAll(getPointOfInterestForecastsAggregate(org.getOrganizationId(), cropOrganismIds, theDate, user)) cropOrganismIds, theDate, user)));
); } else {
}
else
{
organizationIds.stream().forEach( organizationIds.stream().forEach(
orgId-> poisWithAggregate.addAll(getPointOfInterestForecastsAggregate(orgId, cropOrganismIds, theDate, user)) orgId -> poisWithAggregate
); .addAll(getPointOfInterestForecastsAggregate(orgId, cropOrganismIds, theDate, user)));
} }
//System.out.println(this.getClass().getName() + " DEBUG: getPointOfInterestForecastsAggregate took " + (new Date().getTime() - benchmark.getTime()) + " ms to complete."); // System.out.println(this.getClass().getName() + " DEBUG: getPointOfInterestForecastsAggregate took " + (new
// Date().getTime() - benchmark.getTime()) + " ms to complete.");
GISEntityUtil gisUtil = new GISEntityUtil(); GISEntityUtil gisUtil = new GISEntityUtil();
for(PointOfInterest poiWithAggregate:poisWithAggregate) for (PointOfInterest poiWithAggregate : poisWithAggregate) {
{
// If it's an inactive weather station, we don't produce a placemark // If it's an inactive weather station, we don't produce a placemark
if(poiWithAggregate instanceof PointOfInterestWeatherStation if (poiWithAggregate instanceof PointOfInterestWeatherStation
&& ((PointOfInterestWeatherStation) poiWithAggregate).getActive().equals(Boolean.FALSE) && ((PointOfInterestWeatherStation) poiWithAggregate).getActive().equals(Boolean.FALSE)) {
)
{
continue; continue;
} }
// Adding infoUri (direct link to weather station information) as extra attribute // Adding infoUri (direct link to weather station information) as extra attribute
String infoUriValue = ""; String infoUriValue = "";
if(poiWithAggregate instanceof PointOfInterestWeatherStation) if (poiWithAggregate instanceof PointOfInterestWeatherStation) {
{ String infoUriExpression = ((PointOfInterestWeatherStation) poiWithAggregate)
String infoUriExpression = ((PointOfInterestWeatherStation) poiWithAggregate).getWeatherStationDataSourceId().getInfoUriExpression(); .getWeatherStationDataSourceId().getInfoUriExpression();
if(!infoUriExpression.isEmpty()) if (!infoUriExpression.isEmpty()) {
{ infoUriValue = String.format(infoUriExpression,
infoUriValue = String.format(infoUriExpression, ((PointOfInterestWeatherStation) poiWithAggregate).getWeatherStationRemoteId()); ((PointOfInterestWeatherStation) poiWithAggregate).getWeatherStationRemoteId());
} }
} }
Data infoUri = new Data(infoUriValue); Data infoUri = new Data(infoUriValue);
...@@ -884,43 +844,44 @@ public class ForecastBean { ...@@ -884,43 +844,44 @@ public class ForecastBean {
dataList.add(stationName); dataList.add(stationName);
ExtendedData extendedData = document.createAndSetExtendedData() ExtendedData extendedData = document.createAndSetExtendedData()
.withData(dataList); .withData(dataList);
final Placemark placemark = document.createAndAddPlacemark() final Placemark placemark = document.createAndAddPlacemark()
//.withName(poiWithAggregate.getName()) // .withName(poiWithAggregate.getName())
.withDescription("<![CDATA[Mangler informasjon om varsler for " + poiWithAggregate.getName() + "]]>") .withDescription(
.withStyleUrl("#warning_type_" "<![CDATA[Mangler informasjon om varsler for " + poiWithAggregate.getName() + "]]>")
+ (poiWithAggregate.getProperties().get("forecastsAggregate") != null ? poiWithAggregate.getProperties().get("forecastsAggregate") : "0") .withStyleUrl("#warning_type_"
) + (poiWithAggregate.getProperties().get("forecastsAggregate") != null
.withId(poiWithAggregate.getPointOfInterestId().toString()) ? poiWithAggregate.getProperties().get("forecastsAggregate")
.withExtendedData(extendedData); : "0"))
.withId(poiWithAggregate.getPointOfInterestId().toString())
.withExtendedData(extendedData);
final Point point = placemark.createAndSetPoint(); final Point point = placemark.createAndSetPoint();
List<Coordinate> coord = point.createAndSetCoordinates(); List<Coordinate> coord = point.createAndSetCoordinates();
coord.add(gisUtil.getKMLCoordinateFromJTSCoordinate(poiWithAggregate.getGisGeom().getCoordinate())); coord.add(gisUtil.getKMLCoordinateFromJTSCoordinate(poiWithAggregate.getGisGeom().getCoordinate()));
} }
//System.out.println(kml.marshal()); // System.out.println(kml.marshal());
return kml; return kml;
} }
/** /**
* The table forecast_result_cache always should contain the forecast * The table forecast_result_cache always should contain the forecast results from TODAY (The system's time, which
* results from TODAY (The system's time, which is configurable) * is configurable)
*/ */
public void updateForecastResultCacheTable() public void updateForecastResultCacheTable() {
{ // Because we might be in completely different time zones,
// Because we might be in completely different time zones,
// Today must stretch from UTC 00:00 -12h to UTC 24:00 +12h, ie 48 hours // Today must stretch from UTC 00:00 -12h to UTC 24:00 +12h, ie 48 hours
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
cal.setTime(SystemTime.getSystemTime()); cal.setTime(SystemTime.getSystemTime());
cal.set(Calendar.HOUR_OF_DAY, 12); cal.set(Calendar.HOUR_OF_DAY, 12);
cal.set(Calendar.MINUTE,0); cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND,0); cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0); cal.set(Calendar.MILLISECOND, 0);
cal.add(Calendar.DATE, -1); cal.add(Calendar.DATE, -1);
Date startTime = cal.getTime(); Date startTime = cal.getTime();
cal.add(Calendar.DATE,2); cal.add(Calendar.DATE, 2);
Date endTime = cal.getTime(); Date endTime = cal.getTime();
String transactionSQL = new StringBuilder() String transactionSQL = new StringBuilder()
.append("BEGIN;") .append("BEGIN;")
...@@ -936,55 +897,53 @@ public class ForecastBean { ...@@ -936,55 +897,53 @@ public class ForecastBean {
.append(" );") .append(" );")
.append("END;") .append("END;")
.toString(); .toString();
Query query = em.createNativeQuery(transactionSQL); Query query = em.createNativeQuery(transactionSQL);
query.setParameter("startTime", startTime); query.setParameter("startTime", startTime);
query.setParameter("endTime", endTime); query.setParameter("endTime", endTime);
query.setParameter("currentDate", SystemTime.getSystemTime()); query.setParameter("currentDate", SystemTime.getSystemTime());
query.executeUpdate(); query.executeUpdate();
} }
/** /**
* The table forecast_summary should contain forecast summaries * The table forecast_summary should contain forecast summaries from +/- 10 days related to TODAY (The system's
* from +/- 10 days related to TODAY (The system's time, which is configurable) * time, which is configurable)
*/ */
public void updateForecastSummaryTable(Date currentDate) public void updateForecastSummaryTable(Date currentDate) {
{ //
//
// Collect all forecasts that are active TODAY // Collect all forecasts that are active TODAY
// This // This
List<ForecastConfiguration> activeForecasts = em.createNamedQuery("ForecastConfiguration.findAllActiveAtDate") List<ForecastConfiguration> activeForecasts = em.createNamedQuery("ForecastConfiguration.findAllActiveAtDate")
.setParameter("currentDate", currentDate).getResultList(); .setParameter("currentDate", currentDate).getResultList();
// Loop through them // Loop through them
List<Long> activeForecastIds = new ArrayList<>(); List<Long> activeForecastIds = new ArrayList<>();
Query deleteQ = em.createNativeQuery( Query deleteQ = em.createNativeQuery(
"DELETE FROM forecast_summary " "DELETE FROM forecast_summary "
+ "WHERE forecast_configuration_id = :forecastConfigurationId"); + "WHERE forecast_configuration_id = :forecastConfigurationId");
Query findQ = em.createNamedQuery("ForecastResult.findByForecastConfigurationIdAndPeriod"); Query findQ = em.createNamedQuery("ForecastResult.findByForecastConfigurationIdAndPeriod");
for(ForecastConfiguration forecastConfiguration:activeForecasts) for (ForecastConfiguration forecastConfiguration : activeForecasts) {
{
activeForecastIds.add(forecastConfiguration.getForecastConfigurationId()); activeForecastIds.add(forecastConfiguration.getForecastConfigurationId());
//System.out.println("forecastConfig id=" + forecastConfiguration.getForecastConfigurationId()); // System.out.println("forecastConfig id=" + forecastConfiguration.getForecastConfigurationId());
// Delete previous summaries for the specific forecast (one at a time, // Delete previous summaries for the specific forecast (one at a time,
// to prevent loss of data in case of software error) // to prevent loss of data in case of software error)
deleteQ.setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId()) deleteQ.setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId())
.executeUpdate(); .executeUpdate();
// Get all results that are within +/- 10 days from TODAY (taking // Get all results that are within +/- 10 days from TODAY (taking
// time zone into account) // time zone into account)
TimeZone forecastTimeZone = forecastConfiguration.getTimeZone() != null ? TimeZone forecastTimeZone = forecastConfiguration.getTimeZone() != null
TimeZone.getTimeZone(forecastConfiguration.getTimeZone()) ? TimeZone.getTimeZone(forecastConfiguration.getTimeZone())
: TimeZone.getTimeZone(forecastConfiguration.getVipsLogicUserId().getOrganizationId().getDefaultTimeZone()) : TimeZone.getTimeZone(
; forecastConfiguration.getVipsLogicUserId().getOrganizationId().getDefaultTimeZone());
Calendar cal = Calendar.getInstance(forecastTimeZone); Calendar cal = Calendar.getInstance(forecastTimeZone);
cal.setTime(currentDate); cal.setTime(currentDate);
cal.add(Calendar.DATE, -10); cal.add(Calendar.DATE, -10);
cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE,0); cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND,0); cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND,0); cal.set(Calendar.MILLISECOND, 0);
Date tenDaysAgo = cal.getTime(); Date tenDaysAgo = cal.getTime();
cal.add(Calendar.DATE, 20); cal.add(Calendar.DATE, 20);
Date tenDaysAhead = cal.getTime(); Date tenDaysAhead = cal.getTime();
...@@ -993,174 +952,166 @@ public class ForecastBean { ...@@ -993,174 +952,166 @@ public class ForecastBean {
.setParameter("timeEnd", tenDaysAhead) .setParameter("timeEnd", tenDaysAhead)
.setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId()) .setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId())
.getResultList(); .getResultList();
// Loop through each day (take timezone into account!), find worst warning // Loop through each day (take timezone into account!), find worst warning
Collections.sort(results); Collections.sort(results);
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
format.setTimeZone(forecastTimeZone); format.setTimeZone(forecastTimeZone);
Map<String, Integer> resultDailyAggregate = new HashMap<>(); Map<String, Integer> resultDailyAggregate = new HashMap<>();
for(ForecastResult result:results) for (ForecastResult result : results) {
{
String dayStamp = format.format(result.getValidTimeStart()); String dayStamp = format.format(result.getValidTimeStart());
Integer currentWorstCode = resultDailyAggregate.get(dayStamp); Integer currentWorstCode = resultDailyAggregate.get(dayStamp);
resultDailyAggregate.put(dayStamp, resultDailyAggregate.put(dayStamp,
Math.max( Math.max(
currentWorstCode != null ? currentWorstCode : 0, currentWorstCode != null ? currentWorstCode : 0,
result.getWarningStatus() result.getWarningStatus()));
)
);
} }
for(String dayStamp: resultDailyAggregate.keySet()) for (String dayStamp : resultDailyAggregate.keySet()) {
{
Date aggregateDay; Date aggregateDay;
try { try {
// PostgreSQL date is a mess. Need to convert to default timezone to get it right // PostgreSQL date is a mess. Need to convert to default timezone to get it right
aggregateDay = new WeatherUtil().changeDateTimeZone(format.parse(dayStamp), forecastTimeZone, TimeZone.getDefault()); aggregateDay = new WeatherUtil().changeDateTimeZone(format.parse(dayStamp), forecastTimeZone,
TimeZone.getDefault());
ForecastSummaryPK summaryPK = new ForecastSummaryPK( ForecastSummaryPK summaryPK = new ForecastSummaryPK(
forecastConfiguration.getForecastConfigurationId(), forecastConfiguration.getForecastConfigurationId(),
aggregateDay aggregateDay);
);
ForecastSummary summary = new ForecastSummary(summaryPK); ForecastSummary summary = new ForecastSummary(summaryPK);
summary.setSummaryCreatedTime(new Date()); summary.setSummaryCreatedTime(new Date());
summary.setWarningStatus(resultDailyAggregate.get(dayStamp)); summary.setWarningStatus(resultDailyAggregate.get(dayStamp));
em.persist(summary); em.persist(summary);
} catch (ParseException ex) { } catch (ParseException ex) {
Logger.getLogger(ForecastBean.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(ForecastBean.class.getName()).log(Level.SEVERE, null, ex);
System.out.println(this.getClass().getName() + " [updateForecastSummaryTable]: Error parsing date " + dayStamp); System.out.println(this.getClass().getName() + " [updateForecastSummaryTable]: Error parsing date "
+ dayStamp);
} }
} }
//em.flush(); // em.flush();
} }
if(activeForecastIds != null && ! activeForecastIds.isEmpty()) if (activeForecastIds != null && !activeForecastIds.isEmpty()) {
{
// Delete all summaries from not active forecasts // Delete all summaries from not active forecasts
em.createNativeQuery("DELETE FROM forecast_summary " em.createNativeQuery("DELETE FROM forecast_summary "
+ "WHERE forecast_configuration_id NOT IN :activeForecastIds") + "WHERE forecast_configuration_id NOT IN :activeForecastIds")
.setParameter("activeForecastIds", activeForecastIds) .setParameter("activeForecastIds", activeForecastIds)
.executeUpdate(); .executeUpdate();
} } else {
else
{
em.createNativeQuery("TRUNCATE forecast_summary").executeUpdate(); em.createNativeQuery("TRUNCATE forecast_summary").executeUpdate();
} }
} }
public List<ForecastConfiguration> getForecastConfigurationWithSummaries(List<Long> forecastConfigurationIds) public List<ForecastConfiguration> getForecastConfigurationWithSummaries(List<Long> forecastConfigurationIds) {
{
List<ForecastConfiguration> retVal = em.createNamedQuery("ForecastConfiguration.findByForecastConfigurationIds") List<ForecastConfiguration> retVal = em.createNamedQuery("ForecastConfiguration.findByForecastConfigurationIds")
.setParameter("forecastConfigurationIds", forecastConfigurationIds) .setParameter("forecastConfigurationIds", forecastConfigurationIds)
.getResultList(); .getResultList();
for(ForecastConfiguration config: retVal) for (ForecastConfiguration config : retVal) {
{
Query q = em.createNamedQuery("ForecastSummary.findByForecastConfigurationId"); Query q = em.createNamedQuery("ForecastSummary.findByForecastConfigurationId");
config.setForecastSummaries( config.setForecastSummaries(
q.setParameter("forecastConfigurationId", config.getForecastConfigurationId()) q.setParameter("forecastConfigurationId", config.getForecastConfigurationId())
.getResultList() .getResultList());
);
} }
return retVal; return retVal;
} }
/** /**
* Finds the forecast configuration summaries for a given organization and that this user has access to * Finds the forecast configuration summaries for a given organization and that this user has access to
*
* @param organizationId * @param organizationId
* @return * @return
*/ */
public List<ForecastConfiguration> getForecastConfigurationSummaries(Integer organizationId, VipsLogicUser user) public List<ForecastConfiguration> getForecastConfigurationSummaries(Integer organizationId, VipsLogicUser user) {
{
List<ForecastSummary> summaries = em.createNamedQuery("ForecastSummary.findByOrganizationId") List<ForecastSummary> summaries = em.createNamedQuery("ForecastSummary.findByOrganizationId")
.setParameter("organizationId", em.find(Organization.class, organizationId)) .setParameter("organizationId", em.find(Organization.class, organizationId))
.getResultList(); .getResultList();
Map<Long, List<ForecastSummary>> mappedSummaries = new HashMap<>(); Map<Long, List<ForecastSummary>> mappedSummaries = new HashMap<>();
summaries.forEach((s) -> { summaries.forEach((s) -> {
List<ForecastSummary> summaryForForecast = mappedSummaries.get(s.getForecastSummaryPK().getForecastConfigurationId()) != null ? List<ForecastSummary> summaryForForecast =
mappedSummaries.get(s.getForecastSummaryPK().getForecastConfigurationId()) : mappedSummaries.get(s.getForecastSummaryPK().getForecastConfigurationId()) != null
new ArrayList<>(); ? mappedSummaries.get(s.getForecastSummaryPK().getForecastConfigurationId())
: new ArrayList<>();
summaryForForecast.add(s); summaryForForecast.add(s);
mappedSummaries.put(s.getForecastSummaryPK().getForecastConfigurationId(), summaryForForecast); mappedSummaries.put(s.getForecastSummaryPK().getForecastConfigurationId(), summaryForForecast);
}); });
if(mappedSummaries.size() > 0) if (mappedSummaries.size() > 0) {
{ List<ForecastConfiguration> configurations =
List<ForecastConfiguration> configurations = em.createNamedQuery("ForecastConfiguration.findByForecastConfigurationIds").setParameter("forecastConfigurationIds", mappedSummaries.keySet()).getResultList(); em.createNamedQuery("ForecastConfiguration.findByForecastConfigurationIds")
.setParameter("forecastConfigurationIds", mappedSummaries.keySet()).getResultList();
// Do some authorization. // Do some authorization.
configurations = configurations.stream().filter(fc -> this.isUserAuthorizedForForecastConfiguration(fc, user)).collect(Collectors.toList()); configurations = configurations.stream()
.filter(fc -> this.isUserAuthorizedForForecastConfiguration(fc, user)).collect(Collectors.toList());
configurations.forEach((conf) -> { configurations.forEach((conf) -> {
conf.setForecastSummaries(mappedSummaries.get(conf.getForecastConfigurationId())); conf.setForecastSummaries(mappedSummaries.get(conf.getForecastConfigurationId()));
}); });
return configurations; return configurations;
} } else {
else
{
return new ArrayList<>(); return new ArrayList<>();
} }
} }
/** /**
* Selects the "worst" (highest infection risk) warning status for forecasts * Selects the "worst" (highest infection risk) warning status for forecasts running at the pois connected to the
* running at the pois connected to the given organization * given organization
*
* @param organizationId Filter for organization * @param organizationId Filter for organization
* @param cropOrganismIds Filter for crops * @param cropOrganismIds Filter for crops
* @param theDate Filter for date. If theDate=systemDate, data is fetched from the caching table forecast_result_cache * @param theDate Filter for date. If theDate=systemDate, data is fetched from the caching table
* forecast_result_cache
* @param user if not null: Include private forecasts for this user * @param user if not null: Include private forecasts for this user
* @return * @return
*/ */
private List<PointOfInterest> getPointOfInterestForecastsAggregate( private List<PointOfInterest> getPointOfInterestForecastsAggregate(
Integer organizationId, Integer organizationId,
List<Integer> cropOrganismIds, List<Integer> cropOrganismIds,
Date theDate, Date theDate,
VipsLogicUser user VipsLogicUser user) {
) {
// TODO: More precise gathering of POIs... // TODO: More precise gathering of POIs...
List<PointOfInterest> pois; List<PointOfInterest> pois;
if(organizationId != null && organizationId > 0) if (organizationId != null && organizationId > 0) {
{
pois = em.createNamedQuery("PointOfInterest.findForecastLocationsByOrganizationId") pois = em.createNamedQuery("PointOfInterest.findForecastLocationsByOrganizationId")
.setParameter("organizationId", em.find(Organization.class, organizationId)) .setParameter("organizationId", em.find(Organization.class, organizationId))
.getResultList(); .getResultList();
} } else {
else
{
pois = em.createNamedQuery("PointOfInterest.findAll").getResultList(); pois = em.createNamedQuery("PointOfInterest.findAll").getResultList();
} }
String dateFormat = "yyyy-MM-dd"; String dateFormat = "yyyy-MM-dd";
SimpleDateFormat format = new SimpleDateFormat(dateFormat); SimpleDateFormat format = new SimpleDateFormat(dateFormat);
// If theDate=systemDate, data is fetched from the caching table forecast_result_cache // If theDate=systemDate, data is fetched from the caching table forecast_result_cache
String tableName = (format.format(theDate).equals(format.format(SystemTime.getSystemTime()))) ? "forecast_result_cache" : "forecast_result"; String tableName =
//this.updateForecastResultCacheTable(); (format.format(theDate).equals(format.format(SystemTime.getSystemTime()))) ? "forecast_result_cache"
: "forecast_result";
// this.updateForecastResultCacheTable();
Calendar cal = Calendar.getInstance(); Calendar cal = Calendar.getInstance();
cal.setTime(theDate); cal.setTime(theDate);
WeatherUtil wUtil = new WeatherUtil(); WeatherUtil wUtil = new WeatherUtil();
for(PointOfInterest poi: pois) for (PointOfInterest poi : pois) {
{
Date midnight = wUtil.normalizeToExactDate(theDate, TimeZone.getTimeZone(poi.getTimeZone())); Date midnight = wUtil.normalizeToExactDate(theDate, TimeZone.getTimeZone(poi.getTimeZone()));
cal.setTime(theDate); cal.setTime(theDate);
cal.add(Calendar.DATE, 1); cal.add(Calendar.DATE, 1);
Date nextMidnight = cal.getTime(); Date nextMidnight = cal.getTime();
String sql = "SELECT max(warning_status) FROM " + tableName + " \n" + String sql = "SELECT max(warning_status) FROM " + tableName + " \n" +
"WHERE forecast_configuration_id IN( \n" + "WHERE forecast_configuration_id IN( \n" +
" SELECT forecast_configuration_id \n" + " SELECT forecast_configuration_id \n" +
" FROM forecast_configuration \n" + " FROM forecast_configuration \n" +
" WHERE forecast_configuration_id > 0 \n" + " WHERE forecast_configuration_id > 0 \n" +
(user == null ? (user == null ? " AND is_private IS FALSE \n"
" AND is_private IS FALSE \n" : " AND (is_private IS FALSE OR (is_private IS TRUE AND vips_logic_user_id=:vipsLogicUserId))")
:" AND (is_private IS FALSE OR (is_private IS TRUE AND vips_logic_user_id=:vipsLogicUserId))" +
) + " AND location_point_of_interest_id=:locationPointOfInterestId \n" +
" AND location_point_of_interest_id=:locationPointOfInterestId \n" + (cropOrganismIds != null && !cropOrganismIds.isEmpty()
(cropOrganismIds != null && ! cropOrganismIds.isEmpty() ? " AND crop_organism_id IN (" + StringUtils.join(cropOrganismIds, ",") + ") " : "") + ? " AND crop_organism_id IN (" + StringUtils.join(cropOrganismIds, ",") + ") "
")\n" + : "")
"AND valid_time_start between :midnight AND :nextMidnight"; +
//System.out.println(poi.getName() + " SQL=" + sql); ")\n" +
"AND valid_time_start between :midnight AND :nextMidnight";
// System.out.println(poi.getName() + " SQL=" + sql);
Query q = em.createNativeQuery(sql); Query q = em.createNativeQuery(sql);
if(user != null) if (user != null) {
{
q.setParameter("vipsLogicUserId", user); q.setParameter("vipsLogicUserId", user);
} }
q.setParameter("locationPointOfInterestId", poi.getPointOfInterestId()); q.setParameter("locationPointOfInterestId", poi.getPointOfInterestId());
...@@ -1168,152 +1119,148 @@ public class ForecastBean { ...@@ -1168,152 +1119,148 @@ public class ForecastBean {
q.setParameter("nextMidnight", nextMidnight); q.setParameter("nextMidnight", nextMidnight);
Integer result = (Integer) q.getSingleResult(); Integer result = (Integer) q.getSingleResult();
poi.getProperties().put("forecastsAggregate", result); poi.getProperties().put("forecastsAggregate", result);
} }
return pois; return pois;
} }
/** /**
* Returns the latest forecast results for given point of interest * Returns the latest forecast results for given point of interest
*
* @param poiId * @param poiId
* @return * @return
*/ */
public Map<String, Object> getLatestForecastResultsForPoi(Integer poiId) { public Map<String, Object> getLatestForecastResultsForPoi(Integer poiId) {
Map<String, Object> retVal = new HashMap<>(); Map<String, Object> retVal = new HashMap<>();
PointOfInterest poi = em.find(PointOfInterest.class, poiId); PointOfInterest poi = em.find(PointOfInterest.class, poiId);
List<ForecastConfiguration> forecastConfigurations = List<ForecastConfiguration> forecastConfigurations =
em.createNamedQuery("ForecastConfiguration.findByLocationPointOfInterestId") em.createNamedQuery("ForecastConfiguration.findByLocationPointOfInterestId")
.setParameter("locationPointOfInterestId", poi) .setParameter("locationPointOfInterestId", poi)
.getResultList(); .getResultList();
HashMap<Long,ForecastConfiguration> mappedForecastConfigurations = new HashMap<>(); HashMap<Long, ForecastConfiguration> mappedForecastConfigurations = new HashMap<>();
List<ForecastResult> results = new ArrayList<>(); List<ForecastResult> results = new ArrayList<>();
for(ForecastConfiguration forecastConfiguration:forecastConfigurations) for (ForecastConfiguration forecastConfiguration : forecastConfigurations) {
{ if (forecastConfiguration.getIsPrivate()) {
if(forecastConfiguration.getIsPrivate())
{
continue; continue;
} }
mappedForecastConfigurations.put(forecastConfiguration.getForecastConfigurationId(), forecastConfiguration); mappedForecastConfigurations.put(forecastConfiguration.getForecastConfigurationId(), forecastConfiguration);
Query q = em.createNativeQuery( Query q = em.createNativeQuery(
"SELECT * FROM forecast_result WHERE forecast_configuration_id = :forecastConfigurationId " "SELECT * FROM forecast_result WHERE forecast_configuration_id = :forecastConfigurationId "
+ "AND valid_time_start = (SELECT max(valid_time_start) FROM forecast_result WHERE forecast_configuration_id = :forecastConfigurationId)", + "AND valid_time_start = (SELECT max(valid_time_start) FROM forecast_result WHERE forecast_configuration_id = :forecastConfigurationId)",
ForecastResult.class ForecastResult.class);
);
q.setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId()); q.setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId());
try try {
{ results.add((ForecastResult) q.getSingleResult());
results.add((ForecastResult)q.getSingleResult()); } catch (NoResultException ex) {
}
catch(NoResultException ex)
{
// This means that the forecast exists, but that there have not been any valid forecast results created // This means that the forecast exists, but that there have not been any valid forecast results created
// For example, it might be too early to start any calculation // For example, it might be too early to start any calculation
} }
} }
retVal.put("forecastConfigurations", mappedForecastConfigurations); retVal.put("forecastConfigurations", mappedForecastConfigurations);
retVal.put("results", results); retVal.put("results", results);
retVal.put("pointOfInterest", poi); retVal.put("pointOfInterest", poi);
return retVal; return retVal;
} }
public ForecastConfiguration storeNewMultipleForecastConfiguration(Integer weatherStationPointOfInterestId,Map<String, FormField> formFields, Map<String, FormField> modelSpecificFormFields) { public ForecastConfiguration storeNewMultipleForecastConfiguration(Integer weatherStationPointOfInterestId,
Map<String, FormField> formFields, Map<String, FormField> modelSpecificFormFields) {
ForecastConfiguration forecastConfiguration = new ForecastConfiguration(); ForecastConfiguration forecastConfiguration = new ForecastConfiguration();
forecastConfiguration.setModelId(formFields.get("modelId").getWebValue()); forecastConfiguration.setModelId(formFields.get("modelId").getWebValue());
forecastConfiguration.setCropOrganismId(em.find(Organism.class, formFields.get("cropOrganismId").getValueAsInteger())); forecastConfiguration
forecastConfiguration.setPestOrganismId(em.find(Organism.class, formFields.get("pestOrganismId").getValueAsInteger())); .setCropOrganismId(em.find(Organism.class, formFields.get("cropOrganismId").getValueAsInteger()));
forecastConfiguration
.setPestOrganismId(em.find(Organism.class, formFields.get("pestOrganismId").getValueAsInteger()));
forecastConfiguration.setIsPrivate(formFields.get("isPrivate").getWebValue() != null); forecastConfiguration.setIsPrivate(formFields.get("isPrivate").getWebValue() != null);
// In the multiple form, location and weatherstation is the same // In the multiple form, location and weatherstation is the same
PointOfInterest locationPoi = em.find(PointOfInterest.class, weatherStationPointOfInterestId); PointOfInterest locationPoi = em.find(PointOfInterest.class, weatherStationPointOfInterestId);
forecastConfiguration.setLocationPointOfInterestId(locationPoi); forecastConfiguration.setLocationPointOfInterestId(locationPoi);
PointOfInterest weatherStationPoi = em.find(PointOfInterestWeatherStation.class, weatherStationPointOfInterestId); PointOfInterest weatherStationPoi =
em.find(PointOfInterestWeatherStation.class, weatherStationPointOfInterestId);
forecastConfiguration.setWeatherStationPointOfInterestId(weatherStationPoi); forecastConfiguration.setWeatherStationPointOfInterestId(weatherStationPoi);
String timeZone = formFields.get("timeZone").getWebValue(); String timeZone = formFields.get("timeZone").getWebValue();
forecastConfiguration.setTimeZone(timeZone); forecastConfiguration.setTimeZone(timeZone);
forecastConfiguration.setDateStart(formFields.get("dateStart").getValueAsDate()); forecastConfiguration.setDateStart(formFields.get("dateStart").getValueAsDate());
forecastConfiguration.setDateEnd(formFields.get("dateEnd").getValueAsDate()); forecastConfiguration.setDateEnd(formFields.get("dateEnd").getValueAsDate());
VipsLogicUser forecastConfigurationUser = em.find(VipsLogicUser.class, formFields.get("vipsLogicUserId").getValueAsInteger()); VipsLogicUser forecastConfigurationUser =
em.find(VipsLogicUser.class, formFields.get("vipsLogicUserId").getValueAsInteger());
forecastConfiguration.setVipsCoreUserId(forecastConfigurationUser); forecastConfiguration.setVipsCoreUserId(forecastConfigurationUser);
forecastConfiguration = em.merge(forecastConfiguration); forecastConfiguration = em.merge(forecastConfiguration);
// Store new values // Store new values
for(FormField field : modelSpecificFormFields.values()) for (FormField field : modelSpecificFormFields.values()) {
{
String deCamelizedFieldName = getDeCamelizedFieldName(forecastConfiguration.getModelId(), field.getName()); String deCamelizedFieldName = getDeCamelizedFieldName(forecastConfiguration.getModelId(), field.getName());
ForecastModelConfiguration forecastModelConfiguration = new ForecastModelConfiguration(forecastConfiguration.getForecastConfigurationId(), deCamelizedFieldName); ForecastModelConfiguration forecastModelConfiguration = new ForecastModelConfiguration(
forecastConfiguration.getForecastConfigurationId(), deCamelizedFieldName);
forecastModelConfiguration.setParameterValue(field.getWebValue()); forecastModelConfiguration.setParameterValue(field.getWebValue());
em.merge(forecastModelConfiguration); em.merge(forecastModelConfiguration);
} }
return forecastConfiguration; return forecastConfiguration;
} }
public List<ForecastConfiguration> getPrivateForecastConfigurationSummaries(VipsLogicUser user) { public List<ForecastConfiguration> getPrivateForecastConfigurationSummaries(VipsLogicUser user) {
List<ForecastConfiguration> forecastConfigurations = this.getPrivateForecastConfigurationsForUser(user.getUserId()); List<ForecastConfiguration> forecastConfigurations =
this.getPrivateForecastConfigurationsForUser(user.getUserId());
// TODO: Filter forecastconfigurations based on criteria (activity, crops, geography etc) // TODO: Filter forecastconfigurations based on criteria (activity, crops, geography etc)
List<ForecastConfiguration> filteredConfigs = new ArrayList<>(); List<ForecastConfiguration> filteredConfigs = new ArrayList<>();
Query q = em.createNamedQuery("ForecastSummary.findByForecastConfigurationId"); Query q = em.createNamedQuery("ForecastSummary.findByForecastConfigurationId");
for(ForecastConfiguration config: forecastConfigurations) for (ForecastConfiguration config : forecastConfigurations) {
{
config.setForecastSummaries( config.setForecastSummaries(
q.setParameter("forecastConfigurationId", config.getForecastConfigurationId()) q.setParameter("forecastConfigurationId", config.getForecastConfigurationId())
.getResultList() .getResultList());
); if (config.getForecastSummaries() != null && !config.getForecastSummaries().isEmpty()) {
if(config.getForecastSummaries() != null && !config.getForecastSummaries().isEmpty())
{
filteredConfigs.add(config); filteredConfigs.add(config);
} }
} }
return filteredConfigs; return filteredConfigs;
} }
/** /**
* *
* @return only the models that have an existing preprocessor in VIPSLogic * @return only the models that have an existing preprocessor in VIPSLogic
*/ */
public List<ModelInformation> getBatchableModels() public List<ModelInformation> getBatchableModels() {
{
List<ModelInformation> modelInfos = em.createNamedQuery("ModelInformation.findAll").getResultList(); List<ModelInformation> modelInfos = em.createNamedQuery("ModelInformation.findAll").getResultList();
return modelInfos.stream() return modelInfos.stream()
.filter(modelInfo -> ModelRunPreprocessorFactory.getModelRunPreprocessor(modelInfo.getModelId()) != null) .filter(modelInfo -> ModelRunPreprocessorFactory
.getModelRunPreprocessor(modelInfo.getModelId()) != null)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public void deleteAllPrivateForecastConfigurationsForUser(VipsLogicUser user) { public void deleteAllPrivateForecastConfigurationsForUser(VipsLogicUser user) {
em.createNativeQuery( em.createNativeQuery(
"DELETE FROM public.forecast_result WHERE forecast_configuration_id IN " "DELETE FROM public.forecast_result WHERE forecast_configuration_id IN "
+ "(" + "("
+ " SELECT forecast_configuration_id " + " SELECT forecast_configuration_id "
+ " FROM public.forecast_configuration " + " FROM public.forecast_configuration "
+ " WHERE is_private IS TRUE " + " WHERE is_private IS TRUE "
+ " AND vips_logic_user_id = :userId " + " AND vips_logic_user_id = :userId "
+ ")" + ")")
) .setParameter("userId", user.getUserId())
.setParameter("userId", user.getUserId()) .executeUpdate();
.executeUpdate();
em.createNativeQuery( em.createNativeQuery(
"DELETE FROM public.forecast_configuration " "DELETE FROM public.forecast_configuration "
+ " WHERE is_private IS TRUE " + " WHERE is_private IS TRUE "
+ " AND vips_logic_user_id = :userId" + " AND vips_logic_user_id = :userId")
) .setParameter("userId", user.getUserId())
.setParameter("userId", user.getUserId()) .executeUpdate();
.executeUpdate();
} }
/** /**
* *
* @param modelId * @param modelId
* @param year * @param year
* @return * @return
*/ */
public List<ForecastConfiguration> getForecastConfigurationsForModel(String modelId, Integer year) { public List<ForecastConfiguration> getForecastConfigurationsForModel(String modelId, Integer year) {
return em.createNamedQuery("ForecastConfiguration.findByModelIdAndYear") return em.createNamedQuery("ForecastConfiguration.findByModelIdAndYear")
......
...@@ -26,11 +26,11 @@ import java.util.HashSet; ...@@ -26,11 +26,11 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.ejb.Stateless; import jakarta.ejb.Stateless;
import javax.persistence.EntityManager; import jakarta.persistence.EntityManager;
import javax.persistence.NoResultException; import jakarta.persistence.NoResultException;
import javax.persistence.PersistenceContext; import jakarta.persistence.PersistenceContext;
import javax.persistence.Query; import jakarta.persistence.Query;
import no.nibio.vips.logic.entity.Message; import no.nibio.vips.logic.entity.Message;
import no.nibio.vips.logic.entity.MessageIllustration; import no.nibio.vips.logic.entity.MessageIllustration;
import no.nibio.vips.logic.entity.MessageIllustrationCaptionLocale; import no.nibio.vips.logic.entity.MessageIllustrationCaptionLocale;
...@@ -43,7 +43,7 @@ import no.nibio.vips.logic.entity.Organization; ...@@ -43,7 +43,7 @@ import no.nibio.vips.logic.entity.Organization;
import no.nibio.vips.logic.entity.VipsLogicUser; import no.nibio.vips.logic.entity.VipsLogicUser;
import no.nibio.vips.logic.util.SystemTime; import no.nibio.vips.logic.util.SystemTime;
import no.nibio.web.forms.FormField; import no.nibio.web.forms.FormField;
import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload2.core.FileItem;
import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.FilenameUtils;
/** /**
...@@ -186,7 +186,7 @@ public class MessageBean { ...@@ -186,7 +186,7 @@ public class MessageBean {
cropCategoryIds.add(Integer.valueOf(cropCategoryId)); cropCategoryIds.add(Integer.valueOf(cropCategoryId));
} }
} }
message.setCropCategoryIds(cropCategoryIds.toArray(new Integer[cropCategoryIds.size()])); message.setCropCategoryIds(cropCategoryIds);
return message; return message;
} }
...@@ -224,7 +224,7 @@ public class MessageBean { ...@@ -224,7 +224,7 @@ public class MessageBean {
} }
// Store file // Store file
item.write(illustration); item.write(illustration.toPath());
// Update MessageIllustrations // Update MessageIllustrations
message = em.merge(message); message = em.merge(message);
......
/* /*
* Copyright (c) 2018 NIBIO <http://www.nibio.no/>. * Copyright (c) 2018 NIBIO <http://www.nibio.no/>.
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU Affero General Public License as published by
...@@ -18,19 +18,13 @@ ...@@ -18,19 +18,13 @@
package no.nibio.vips.logic.controller.session; package no.nibio.vips.logic.controller.session;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.ibm.icu.util.ULocale;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
...@@ -39,16 +33,30 @@ import java.util.Iterator; ...@@ -39,16 +33,30 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Objects;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.ejb.EJB; import org.apache.commons.codec.binary.Base64;
import javax.ejb.Stateless; import org.apache.commons.fileupload2.core.FileItem;
import javax.persistence.EntityManager; import org.apache.commons.io.FilenameUtils;
import javax.persistence.NoResultException; import org.slf4j.Logger;
import javax.persistence.PersistenceContext; import org.slf4j.LoggerFactory;
import javax.persistence.Query; import org.wololo.geojson.Feature;
import javax.servlet.http.HttpServletRequest; import org.wololo.geojson.FeatureCollection;
import org.wololo.geojson.GeoJSONFactory;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.ibm.icu.util.ULocale;
import jakarta.ejb.EJB;
import jakarta.ejb.Stateless;
import jakarta.persistence.EntityManager;
import jakarta.persistence.NoResultException;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;
import jakarta.servlet.http.HttpServletRequest;
import no.nibio.vips.logic.entity.CropCategory; import no.nibio.vips.logic.entity.CropCategory;
import no.nibio.vips.logic.entity.Gis; import no.nibio.vips.logic.entity.Gis;
import no.nibio.vips.logic.entity.Observation; import no.nibio.vips.logic.entity.Observation;
...@@ -56,6 +64,7 @@ import no.nibio.vips.logic.entity.ObservationFormShortcut; ...@@ -56,6 +64,7 @@ import no.nibio.vips.logic.entity.ObservationFormShortcut;
import no.nibio.vips.logic.entity.ObservationIllustration; import no.nibio.vips.logic.entity.ObservationIllustration;
import no.nibio.vips.logic.entity.ObservationIllustrationPK; import no.nibio.vips.logic.entity.ObservationIllustrationPK;
import no.nibio.vips.logic.entity.ObservationStatusType; import no.nibio.vips.logic.entity.ObservationStatusType;
import no.nibio.vips.logic.entity.ObservationTimeSeries;
import no.nibio.vips.logic.entity.Organism; import no.nibio.vips.logic.entity.Organism;
import no.nibio.vips.logic.entity.Organization; import no.nibio.vips.logic.entity.Organization;
import no.nibio.vips.logic.entity.PointOfInterest; import no.nibio.vips.logic.entity.PointOfInterest;
...@@ -63,190 +72,168 @@ import no.nibio.vips.logic.entity.PolygonService; ...@@ -63,190 +72,168 @@ import no.nibio.vips.logic.entity.PolygonService;
import no.nibio.vips.logic.entity.VipsLogicUser; import no.nibio.vips.logic.entity.VipsLogicUser;
import no.nibio.vips.logic.i18n.SessionLocaleUtil; import no.nibio.vips.logic.i18n.SessionLocaleUtil;
import no.nibio.vips.logic.util.SystemTime; import no.nibio.vips.logic.util.SystemTime;
import org.apache.commons.codec.binary.Base64;
import no.nibio.vips.observationdata.ObservationDataSchema; import no.nibio.vips.observationdata.ObservationDataSchema;
import no.nibio.vips.observationdata.ObservationDataSchemaPK; import no.nibio.vips.observationdata.ObservationDataSchemaPK;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wololo.geojson.Feature;
import org.wololo.geojson.FeatureCollection;
import org.wololo.geojson.GeoJSONFactory;
/** /**
* @copyright 2014-2020 <a href="http://www.nibio.no/">NIBIO</a>
* @author Tor-Einar Skog <tor-einar.skog@nibio.no> * @author Tor-Einar Skog <tor-einar.skog@nibio.no>
* @copyright 2014-2020 <a href="http://www.nibio.no/">NIBIO</a>
*/ */
@Stateless @Stateless
public class ObservationBean { public class ObservationBean {
@PersistenceContext(unitName="VIPSLogic-PU") private static final Logger LOGGER = LoggerFactory.getLogger(ObservationBean.class);
@PersistenceContext(unitName = "VIPSLogic-PU")
EntityManager em; EntityManager em;
@EJB @EJB
PointOfInterestBean pointOfInterestBean; PointOfInterestBean pointOfInterestBean;
@EJB @EJB
UserBean userBean; UserBean userBean;
private static Logger LOGGER = LoggerFactory.getLogger(ObservationBean.class); @EJB
ObservationTimeSeriesBean observationTimeSeriesBean;
public List<Observation> getObservations(Integer organizationId)
{ public List<Observation> getObservations(Integer organizationId) {
Organization organization = em.find(Organization.class,organizationId); Organization organization = em.find(Organization.class, organizationId);
List<Observation> observations = em.createNamedQuery("Observation.findByOrganizationId") List<Observation> observations = em.createNamedQuery("Observation.findByOrganizationId")
.setParameter("organizationId", organization) .setParameter("organizationId", organization)
.getResultList(); .getResultList();
observations = this.getObservationsWithGeoInfo(observations); observations = this.getObservationsWithGeoInfo(observations);
observations = this.getObservationsWithLocations(observations); observations = this.getObservationsWithLocations(observations);
observations = this.getObservationsWithObservers(observations); observations = this.getObservationsWithObservers(observations);
return observations; return observations;
} }
public List<Observation> getObservations(Integer organizationId, Date periodStart, Date periodEnd) public List<Observation> getObservations(Integer organizationId, Date periodStart, Date periodEnd) {
{ Organization organization = em.find(Organization.class, organizationId);
Organization organization = em.find(Organization.class,organizationId);
List<Observation> observations = em.createNamedQuery("Observation.findByOrganizationIdAndPeriod") List<Observation> observations = em.createNamedQuery("Observation.findByOrganizationIdAndPeriod")
.setParameter("organizationId", organization) .setParameter("organizationId", organization)
.setParameter("start", periodStart) .setParameter("start", periodStart)
.setParameter("end", periodEnd) .setParameter("end", periodEnd)
.getResultList(); .getResultList();
observations = this.getObservationsWithGeoInfo(observations); observations = this.getObservationsWithGeoInfo(observations);
observations = this.getObservationsWithLocations(observations); observations = this.getObservationsWithLocations(observations);
observations = this.getObservationsWithObservers(observations); observations = this.getObservationsWithObservers(observations);
return observations; return observations;
} }
public List<Observation> getObservations(Integer organizationId, Integer statusTypeId) public List<Observation> getObservations(Integer organizationId, Integer statusTypeId) {
{ Organization organization = em.find(Organization.class, organizationId);
Organization organization= em.find(Organization.class, organizationId);
/*List<VipsLogicUser> users = em.createNamedQuery("VipsLogicUser.findByOrganizationId", VipsLogicUser.class) /*List<VipsLogicUser> users = em.createNamedQuery("VipsLogicUser.findByOrganizationId", VipsLogicUser.class)
.setParameter("organizationId", organization) .setParameter("organizationId", organization)
.getResultList();*/ .getResultList();*/
List<Observation> retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByOrganizationIdAndStatusTypeId") List<Observation> retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByOrganizationIdAndStatusTypeId")
.setParameter("organizationId", organization) .setParameter("organizationId", organization)
.setParameter("statusTypeId", statusTypeId) .setParameter("statusTypeId", statusTypeId)
.getResultList()); .getResultList());
return retVal; return retVal;
} }
public List<Observation> getObservationsForUser(VipsLogicUser user) public List<Observation> getObservationsForUser(VipsLogicUser user) {
{
List<Observation> retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByUserId") List<Observation> retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByUserId")
.setParameter("userId", user.getUserId()) .setParameter("userId", user.getUserId())
.getResultList()); .getResultList());
retVal = this.getObservationsWithLocations(retVal); retVal = this.getObservationsWithLocations(retVal);
retVal = this.getObservationsWithObservers(retVal); retVal = this.getObservationsWithObservers(retVal);
return retVal; return retVal;
} }
public List<Observation> getObservationsLastEditedByUser(VipsLogicUser user) { public List<Observation> getObservationsLastEditedByUser(VipsLogicUser user) {
List<Observation> retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByLastEditedBy") List<Observation> retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByLastEditedBy")
.setParameter("lastEditedBy", user.getUserId()) .setParameter("lastEditedBy", user.getUserId())
.getResultList()); .getResultList());
retVal = this.getObservationsWithLocations(retVal); retVal = this.getObservationsWithLocations(retVal);
retVal = this.getObservationsWithObservers(retVal); retVal = this.getObservationsWithObservers(retVal);
return retVal; return retVal;
} }
public List<Observation> getObservationsStatusChangedByUser(VipsLogicUser user) { public List<Observation> getObservationsStatusChangedByUser(VipsLogicUser user) {
List<Observation> retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByStatusChangedByUserId") List<Observation> retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByStatusChangedByUserId")
.setParameter("statusChangedByUserId", user.getUserId()) .setParameter("statusChangedByUserId", user.getUserId())
.getResultList()); .getResultList());
retVal = this.getObservationsWithLocations(retVal); retVal = this.getObservationsWithLocations(retVal);
retVal = this.getObservationsWithObservers(retVal); retVal = this.getObservationsWithObservers(retVal);
return retVal; return retVal;
} }
public List<Observation> getObservationsForUser(VipsLogicUser user, Date periodStart, Date periodEnd) public List<Observation> getObservationsForUser(VipsLogicUser user, Date periodStart, Date periodEnd) {
{
List<Observation> retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByUserIdAndPeriod") List<Observation> retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByUserIdAndPeriod")
.setParameter("userId", user.getUserId()) .setParameter("userId", user.getUserId())
.setParameter("start", periodStart) .setParameter("start", periodStart)
.setParameter("end", periodEnd) .setParameter("end", periodEnd)
.getResultList()); .getResultList());
retVal = this.getObservationsWithLocations(retVal); retVal = this.getObservationsWithLocations(retVal);
retVal = this.getObservationsWithObservers(retVal); retVal = this.getObservationsWithObservers(retVal);
return retVal; return retVal;
} }
public List<Observation> getObservationsForUser(VipsLogicUser user, Integer statusTypeId) public List<Observation> getObservationsForUser(VipsLogicUser user, Integer statusTypeId) {
{
List<Observation> retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByUserIdAndStatusTypeId") List<Observation> retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByUserIdAndStatusTypeId")
.setParameter("userId", user.getUserId()) .setParameter("userId", user.getUserId())
.setParameter("statusTypeId", statusTypeId) .setParameter("statusTypeId", statusTypeId)
.getResultList()); .getResultList());
return retVal; return retVal;
} }
public Observation getObservation(Integer observationId) public Observation getObservation(Integer observationId) {
{
Observation retVal = em.find(Observation.class, observationId); Observation retVal = em.find(Observation.class, observationId);
if(retVal != null) if (retVal != null) {
{
retVal.setGeoinfos(this.getGeoinfoForObservation(retVal)); retVal.setGeoinfos(this.getGeoinfoForObservation(retVal));
retVal.setUser(em.find(VipsLogicUser.class, retVal.getUserId())); retVal.setUser(em.find(VipsLogicUser.class, retVal.getUserId()));
if(retVal.getLastEditedBy() != null) if (retVal.getLastEditedBy() != null) {
{
retVal.setLastEditedByUser(em.find(VipsLogicUser.class, retVal.getLastEditedBy())); retVal.setLastEditedByUser(em.find(VipsLogicUser.class, retVal.getLastEditedBy()));
} }
} }
return retVal; return retVal;
} }
public List<Gis> getGeoinfoForObservation(Observation obs) public List<Gis> getGeoinfoForObservation(Observation obs) {
{
List<Integer> gisIds = em.createNativeQuery("SELECT gis_id FROM public.gis_observation WHERE observation_id = :observationId") List<Integer> gisIds = em.createNativeQuery("SELECT gis_id FROM public.gis_observation WHERE observation_id = :observationId")
.setParameter("observationId", obs.getObservationId()) .setParameter("observationId", obs.getObservationId())
.getResultList(); .getResultList();
if(gisIds != null && ! gisIds.isEmpty()) if (gisIds != null && !gisIds.isEmpty()) {
{ return em.createNamedQuery("Gis.findByGisIds", Gis.class)
return em.createNamedQuery("Gis.findByGisIds",Gis.class)
.setParameter("gisIds", gisIds) .setParameter("gisIds", gisIds)
.getResultList(); .getResultList();
} } else {
else
{
return null; return null;
} }
} }
public List<Observation> getObservationsWithGeoInfo(List<Observation> observations) public List<Observation> getObservationsWithGeoInfo(List<Observation> observations) {
{ if (observations.isEmpty()) {
if(observations.isEmpty())
{
return observations; return observations;
} }
// Using this method as opposed to db query for each observation, we // Using this method as opposed to db query for each observation, we
// slim the time down from 24 seconds to 270 milliseconds! DB connections are expensive.... // slim the time down from 24 seconds to 270 milliseconds! DB connections are expensive....
// Indexing observations // Indexing observations
Map<Integer, Observation> obsBucket = new HashMap<>(); Map<Integer, Observation> obsBucket = new HashMap<>();
observations.stream().forEach((obs) -> { observations.stream().forEach((obs) -> {
obsBucket.put(obs.getObservationId(), obs); obsBucket.put(obs.getObservationId(), obs);
}); });
// Getting many-to-many relations // Getting many-to-many relations
Query q = em.createNativeQuery("SELECT gis_id, observation_id FROM public.gis_observation WHERE observation_id IN :observationIds"); Query q = em.createNativeQuery("SELECT gis_id, observation_id FROM public.gis_observation WHERE observation_id IN :observationIds");
q.setParameter("observationIds", obsBucket.keySet()); q.setParameter("observationIds", obsBucket.keySet());
List<Object[]> gisObservationIds = q.getResultList(); List<Object[]> gisObservationIds = q.getResultList();
// Collecting and indexing geoInfo // Collecting and indexing geoInfo
Query q2 = em.createNativeQuery("SELECT * FROM public.gis WHERE gis_id IN (SELECT gis_id FROM public.gis_observation WHERE observation_id IN :observationIds)", Gis.class); Query q2 = em.createNativeQuery("SELECT * FROM public.gis WHERE gis_id IN (SELECT gis_id FROM public.gis_observation WHERE observation_id IN :observationIds)", Gis.class);
List<Gis> geoInfos = q2.setParameter("observationIds", obsBucket.keySet()).getResultList(); List<Gis> geoInfos = q2.setParameter("observationIds", obsBucket.keySet()).getResultList();
...@@ -254,7 +241,7 @@ public class ObservationBean { ...@@ -254,7 +241,7 @@ public class ObservationBean {
geoInfos.stream().forEach((geoinfo) -> { geoInfos.stream().forEach((geoinfo) -> {
gisBucket.put(geoinfo.getGisId(), geoinfo); gisBucket.put(geoinfo.getGisId(), geoinfo);
}); });
// Iterating the many-to-many relations, // Iterating the many-to-many relations,
// adding geoinfo to the correct observations // adding geoinfo to the correct observations
gisObservationIds.stream().forEach((gisObsIds) -> { gisObservationIds.stream().forEach((gisObsIds) -> {
...@@ -262,12 +249,11 @@ public class ObservationBean { ...@@ -262,12 +249,11 @@ public class ObservationBean {
Integer observationId = (Integer) gisObsIds[1]; Integer observationId = (Integer) gisObsIds[1];
obsBucket.get(observationId).addGeoInfo(gisBucket.get(gisId)); obsBucket.get(observationId).addGeoInfo(gisBucket.get(gisId));
}); });
return observations; return observations;
} }
/** /**
*
* @param observation * @param observation
* @return The merged object * @return The merged object
*/ */
...@@ -283,14 +269,13 @@ public class ObservationBean { ...@@ -283,14 +269,13 @@ public class ObservationBean {
.setParameter("observationId", retVal.getObservationId()) .setParameter("observationId", retVal.getObservationId())
.executeUpdate(); .executeUpdate();
// Then persist the new ones // Then persist the new ones
if(observation.getGeoinfos() != null && ! observation.getGeoinfos().isEmpty()) if (observation.getGeoinfos() != null && !observation.getGeoinfos().isEmpty()) {
{
observation.getGeoinfos().stream().forEach((gis) -> { observation.getGeoinfos().stream().forEach((gis) -> {
em.persist(gis); em.persist(gis);
}); });
Query q = em.createNativeQuery("INSERT INTO public.gis_observation(gis_id,observation_id) VALUES(:gisId,:observationId)") Query q = em.createNativeQuery("INSERT INTO public.gis_observation(gis_id,observation_id) VALUES(:gisId,:observationId)")
.setParameter("observationId", retVal.getObservationId()); .setParameter("observationId", retVal.getObservationId());
observation.getGeoinfos().stream().forEach((gis) -> { observation.getGeoinfos().stream().forEach((gis) -> {
q.setParameter("gisId", gis.getGisId()) q.setParameter("gisId", gis.getGisId())
.executeUpdate(); .executeUpdate();
...@@ -304,54 +289,49 @@ public class ObservationBean { ...@@ -304,54 +289,49 @@ public class ObservationBean {
em.persist(gis); em.persist(gis);
gises.add(gis); gises.add(gis);
}*/ }*/
// The GisObservations are not included in the merged object, so we should add them // The GisObservations are not included in the merged object, so we should add them
retVal.setGeoinfos(this.getGeoinfoForObservation(retVal)); retVal.setGeoinfos(this.getGeoinfoForObservation(retVal));
return retVal; return retVal;
} }
public void deleteObservation(Integer observationId) { public void deleteObservation(Integer observationId) {
Observation observation = em.find(Observation.class, observationId); Observation observation = em.find(Observation.class, observationId);
if(observation != null) if (observation != null) {
{ // Delete all current group memberships
// Delete all current group memberships
em.createNativeQuery("DELETE FROM public.organization_group_observation WHERE observation_id=:observationId") em.createNativeQuery("DELETE FROM public.organization_group_observation WHERE observation_id=:observationId")
.setParameter("observationId", observation.getObservationId()) .setParameter("observationId", observation.getObservationId())
.executeUpdate(); .executeUpdate();
// Delete all illustrations (including removing files on disk) // Delete all illustrations (including removing files on disk)
String[] filesToDelete = observation.getObservationIllustrationSet().stream() String[] filesToDelete = observation.getObservationIllustrationSet().stream()
.map(ill->ill.getObservationIllustrationPK().getFileName()) .map(ill -> ill.getObservationIllustrationPK().getFileName())
.collect(Collectors.toList()) .collect(Collectors.toList())
.toArray(new String[0]); .toArray(new String[0]);
this.deleteObservationIllustration(observation, filesToDelete); this.deleteObservationIllustration(observation, filesToDelete);
em.remove(observation); em.remove(observation);
} }
} }
/** /**
*
* @param organizationId * @param organizationId
* @param season * @param season
* @return * @return
*/ */
public List<Observation> getBroadcastObservations(Integer organizationId, Integer season) { public List<Observation> getBroadcastObservations(Integer organizationId, Integer season) {
Organization organization= em.find(Organization.class, organizationId); Organization organization = em.find(Organization.class, organizationId);
/*List<VipsLogicUser> users = em.createNamedQuery("VipsLogicUser.findByOrganizationId", VipsLogicUser.class) /*List<VipsLogicUser> users = em.createNamedQuery("VipsLogicUser.findByOrganizationId", VipsLogicUser.class)
.setParameter("organizationId", organization) .setParameter("organizationId", organization)
.getResultList();*/ .getResultList();*/
List<Observation> retVal = null; List<Observation> retVal = null;
if(season == null) if (season == null) {
{ retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByOrganizationIdAndStatusTypeIdAndBroadcastMessage")
retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByOrganizationIdAndStatusTypeIdAndBroadcastMessage")
.setParameter("organizationId", organization) .setParameter("organizationId", organization)
.setParameter("statusTypeId", Observation.STATUS_TYPE_ID_APPROVED) .setParameter("statusTypeId", Observation.STATUS_TYPE_ID_APPROVED)
.getResultList()); .getResultList());
} } else {
else
{
Calendar cal = Calendar.getInstance(); Calendar cal = Calendar.getInstance();
cal.set(season, Calendar.JANUARY, 1, 0, 0, 0); cal.set(season, Calendar.JANUARY, 1, 0, 0, 0);
Date start = cal.getTime(); Date start = cal.getTime();
...@@ -361,31 +341,29 @@ public class ObservationBean { ...@@ -361,31 +341,29 @@ public class ObservationBean {
} }
return retVal; return retVal;
} }
/** /**
*
* @param organizationId * @param organizationId
* @param start When period starts. Default: Jan 1st 2000 * @param start When period starts. Default: Jan 1st 2000
* @param end When period ends. Default: 100 years from now * @param end When period ends. Default: 100 years from now
* @return * @return
*/ */
public List<Observation> getBroadcastObservations(Integer organizationId, Date start, Date end) { public List<Observation> getBroadcastObservations(Integer organizationId, Date start, Date end) {
if(start == null || end == null) if (start == null || end == null) {
{
Calendar cal = Calendar.getInstance(); Calendar cal = Calendar.getInstance();
if(start == null) // Default Jan 1st 2000 if (start == null) // Default Jan 1st 2000
{ {
cal.set(2000, Calendar.JANUARY,1,0,0,0); cal.set(2000, Calendar.JANUARY, 1, 0, 0, 0);
start = cal.getTime(); start = cal.getTime();
} }
if(end == null) // Default: Today + 100 years if (end == null) // Default: Today + 100 years
{ {
cal.setTime(SystemTime.getSystemTime()); cal.setTime(SystemTime.getSystemTime());
cal.add(Calendar.YEAR, 100); cal.add(Calendar.YEAR, 100);
end = cal.getTime(); end = cal.getTime();
} }
} }
Organization organization= em.find(Organization.class, organizationId); Organization organization = em.find(Organization.class, organizationId);
return this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByOrganizationIdAndStatusTypeIdAndBroadcastMessageAndPeriod") return this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByOrganizationIdAndStatusTypeIdAndBroadcastMessageAndPeriod")
.setParameter("organizationId", organization) .setParameter("organizationId", organization)
.setParameter("statusTypeId", Observation.STATUS_TYPE_ID_APPROVED) .setParameter("statusTypeId", Observation.STATUS_TYPE_ID_APPROVED)
...@@ -393,45 +371,42 @@ public class ObservationBean { ...@@ -393,45 +371,42 @@ public class ObservationBean {
.setParameter("end", end) .setParameter("end", end)
.getResultList()); .getResultList());
} }
/** /**
*
* @param observation * @param observation
* @return [OBSERVATION_ILLUSTRATION_PATH]/[ORGANISM_ID]/ * @return [OBSERVATION_ILLUSTRATION_PATH]/[ORGANISM_ID]/
*/ */
private String getFilePath(Observation observation) private String getFilePath(Observation observation) {
{ return System.getProperty("no.nibio.vips.logic.OBSERVATION_ILLUSTRATION_PATH") + "/"
return System.getProperty("no.nibio.vips.logic.OBSERVATION_ILLUSTRATION_PATH") + "/" + observation.getOrganismId();
+ observation.getOrganismId(); }
}
public Observation storeObservationIllustration(Observation observation, String fileName, String base64Data) {
public Observation storeObservationIllustration(Observation observation, String fileName, String base64Data) String[] metaAndData = base64Data.split(",");
{ byte[] imageData = Base64.decodeBase64(metaAndData[1]);
String[] metaAndData = base64Data.split(","); Path path = Paths.get(this.getFilePath(observation) + "/" + fileName);
byte[] imageData = Base64.decodeBase64(metaAndData[1]); try {
Path path = Paths.get(this.getFilePath(observation) + "/" + fileName); // Make sure the directory exists
try { File testDirectoryfile = new File(this.getFilePath(observation));
// Make sure the directory exists if (!testDirectoryfile.exists()) {
File testDirectoryfile = new File(this.getFilePath(observation)); testDirectoryfile.mkdirs();
if(!testDirectoryfile.exists()) }
{ Files.write(path, imageData, StandardOpenOption.CREATE);
testDirectoryfile.mkdirs(); ObservationIllustration newIllustration = new ObservationIllustration(new ObservationIllustrationPK(observation.getObservationId(), fileName));
} newIllustration = em.merge(newIllustration);
Files.write(path,imageData, StandardOpenOption.CREATE);
ObservationIllustration newIllustration = new ObservationIllustration(new ObservationIllustrationPK(observation.getObservationId(), fileName)); // Add the new illustration
newIllustration = em.merge(newIllustration); if (observation.getObservationIllustrationSet() == null) {
observation.setObservationIllustrationSet(new HashSet<ObservationIllustration>());
// Add the new illustration }
if(observation.getObservationIllustrationSet() == null) observation.getObservationIllustrationSet().add(newIllustration);
{
observation.setObservationIllustrationSet(new HashSet<ObservationIllustration>()); return observation;
} } catch (IOException ex) {
observation.getObservationIllustrationSet().add(newIllustration); ex.printStackTrace();
return observation;
return observation; }
}
catch(IOException ex) {ex.printStackTrace(); return observation;}
} }
public Observation storeObservationIllustration(Observation observation, FileItem item) throws Exception { public Observation storeObservationIllustration(Observation observation, FileItem item) throws Exception {
...@@ -442,32 +417,29 @@ public class ObservationBean { ...@@ -442,32 +417,29 @@ public class ObservationBean {
// Check availability, and adapt filename until available // Check availability, and adapt filename until available
Integer fileNameSuffix = 1; Integer fileNameSuffix = 1;
File illustration = new File(filePath + "/" + fileName); File illustration = new File(filePath + "/" + fileName);
while(illustration.exists()) while (illustration.exists()) {
{
fileName = observation.getObservationId() + "_illustration_" + fileNameSuffix + "." + FilenameUtils.getExtension(item.getName()); fileName = observation.getObservationId() + "_illustration_" + fileNameSuffix + "." + FilenameUtils.getExtension(item.getName());
illustration = new File(filePath + "/" + fileName); illustration = new File(filePath + "/" + fileName);
fileNameSuffix++; fileNameSuffix++;
} }
File testDirectoryfile = new File(filePath); File testDirectoryfile = new File(filePath);
// If directory does not exist, create it // If directory does not exist, create it
if(!testDirectoryfile.exists()) if (!testDirectoryfile.exists()) {
{
testDirectoryfile.mkdirs(); testDirectoryfile.mkdirs();
} }
// Store file // Store file
item.write(illustration); item.write(illustration.toPath());
// Update MessageIllustrations // Update MessageIllustrations
observation = em.merge(observation); observation = em.merge(observation);
// Remove the old illustration(s) // Remove the old illustration(s)
ObservationIllustration newIllustration = new ObservationIllustration(new ObservationIllustrationPK(observation.getObservationId(), fileName)); ObservationIllustration newIllustration = new ObservationIllustration(new ObservationIllustrationPK(observation.getObservationId(), fileName));
em.persist(newIllustration); em.persist(newIllustration);
// Add the new illustration // Add the new illustration
if(observation.getObservationIllustrationSet() == null) if (observation.getObservationIllustrationSet() == null) {
{
observation.setObservationIllustrationSet(new HashSet<ObservationIllustration>()); observation.setObservationIllustrationSet(new HashSet<ObservationIllustration>());
} }
observation.getObservationIllustrationSet().add(newIllustration); observation.getObservationIllustrationSet().add(newIllustration);
...@@ -476,127 +448,139 @@ public class ObservationBean { ...@@ -476,127 +448,139 @@ public class ObservationBean {
public Observation deleteObservationIllustration(Observation observation, String[] deleteIllustrations) { public Observation deleteObservationIllustration(Observation observation, String[] deleteIllustrations) {
observation = em.merge(observation); observation = em.merge(observation);
Set <ObservationIllustration> formerIllustrations = observation.getObservationIllustrationSet(); Set<ObservationIllustration> formerIllustrations = observation.getObservationIllustrationSet();
if(formerIllustrations == null) if (formerIllustrations == null) {
{ return observation;
return observation; }
Set<ObservationIllustration> deleteThese = new HashSet<>();
for (String deleteIllustration : deleteIllustrations) {
for (ObservationIllustration formerIllustration : formerIllustrations) {
if (formerIllustration.getObservationIllustrationPK().getFileName()
.equals(deleteIllustration)) {
deleteThese.add(formerIllustration);
}
}
}
for (ObservationIllustration ill : deleteThese) {
observation.getObservationIllustrationSet().remove(ill);
em.remove(ill);
// Physically remove it too
File fileToDelete = new File(this.getFilePath(observation) + "/" + ill.getObservationIllustrationPK().getFileName());
fileToDelete.delete();
} }
Set <ObservationIllustration> deleteThese = new HashSet<>();
for(String deleteIllustration:deleteIllustrations)
{
for(ObservationIllustration formerIllustration:formerIllustrations)
{
if(formerIllustration.getObservationIllustrationPK().getFileName()
.equals(deleteIllustration))
{
deleteThese.add(formerIllustration);
}
}
}
for(ObservationIllustration ill: deleteThese)
{
observation.getObservationIllustrationSet().remove(ill);
em.remove(ill);
// Physically remove it too
File fileToDelete = new File(this.getFilePath(observation) + "/" + ill.getObservationIllustrationPK().getFileName());
fileToDelete.delete();
}
return observation; return observation;
} }
/** /**
* Fetch observations of a particular organism at a particular place and period * Fetch observations of a particular organism at a particular place and period
*
* @param organismId * @param organismId
* @param pointOfInterestId * @param pointOfInterestId
* @param startDate * @param startDate
* @param endDate * @param endDate
* @return * @return
*/ */
public List<no.nibio.vips.observation.Observation> getObservations(Integer organismId, Integer pointOfInterestId, Date startDate, Date endDate) { public List<no.nibio.vips.observation.Observation> getObservations(Integer organismId, Integer pointOfInterestId, Date startDate, Date endDate) {
/*System.out.println("organismId = " + organismId); /*System.out.println("organismId = " + organismId);
System.out.println("pointOfInterestId = " + pointOfInterestId); System.out.println("pointOfInterestId = " + pointOfInterestId);
System.out.println("period= " + startDate + "-" + endDate);*/ System.out.println("period= " + startDate + "-" + endDate);*/
return em.createNativeQuery( return em.createNativeQuery(
"SELECT * FROM public.observation " "SELECT * FROM public.observation "
+ "WHERE organism_id = :organismId " + "WHERE organism_id = :organismId "
+ "AND location_point_of_interest_id = :locationPointOfInterestId " + "AND location_point_of_interest_id = :locationPointOfInterestId "
+ "AND time_of_observation BETWEEN :startDate AND :endDate" + "AND time_of_observation BETWEEN :startDate AND :endDate"
,Observation.class , Observation.class
) )
.setParameter("organismId", organismId) .setParameter("organismId", organismId)
.setParameter("locationPointOfInterestId",pointOfInterestId) .setParameter("locationPointOfInterestId", pointOfInterestId)
.setParameter("startDate", startDate) .setParameter("startDate", startDate)
.setParameter("endDate", endDate) .setParameter("endDate", endDate)
.getResultList(); .getResultList();
} }
public List<Observation> getObservationsWithLocations(List<Observation> observations) { public List<Observation> getObservationsWithLocations(List<Observation> observations) {
Set<Integer> locationPointOfInterestIds = new HashSet<>(); Set<Integer> locationPointOfInterestIds = new HashSet<>();
observations.stream().filter((o) -> (o.getLocationPointOfInterestId() != null)).forEach((o) -> { observations.stream().filter((o) -> (o.getLocationPointOfInterestId() != null)).forEach((o) -> {
locationPointOfInterestIds.add(o.getLocationPointOfInterestId()); locationPointOfInterestIds.add(o.getLocationPointOfInterestId());
}); });
// Nothing to do? // Nothing to do?
if(locationPointOfInterestIds.isEmpty()) if (locationPointOfInterestIds.isEmpty()) {
{
return observations; return observations;
} }
List<PointOfInterest> pois = pointOfInterestBean.getPois(locationPointOfInterestIds); List<PointOfInterest> pois = pointOfInterestBean.getPois(locationPointOfInterestIds);
Map<Integer, PointOfInterest> mappedPois = new HashMap<>(); Map<Integer, PointOfInterest> mappedPois = new HashMap<>();
pois.stream().forEach((poi) -> { pois.stream().forEach((poi) -> {
mappedPois.put(poi.getPointOfInterestId(), poi); mappedPois.put(poi.getPointOfInterestId(), poi);
}); });
observations.stream().filter((o) -> (o.getLocationPointOfInterestId() != null)).forEach((o) -> { observations.stream().filter((o) -> (o.getLocationPointOfInterestId() != null)).forEach((o) -> {
o.setLocation(mappedPois.get(o.getLocationPointOfInterestId())); o.setLocation(mappedPois.get(o.getLocationPointOfInterestId()));
}); });
return observations; return observations;
} }
public List<Observation> getObservationsWithTimeSeries(List<Observation> observations) {
Set<Integer> observationTimeSeriesIds = observations.stream()
.map(Observation::getObservationTimeSeriesId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
if (observationTimeSeriesIds.isEmpty()) {
return observations;
}
List<ObservationTimeSeries> timeSeriesList = observationTimeSeriesBean.getObservationTimeSeriesList(observationTimeSeriesIds);
Map<Integer, ObservationTimeSeries> timeSeriesMap = timeSeriesList.stream()
.collect(Collectors.toMap(ObservationTimeSeries::getObservationTimeSeriesId, Function.identity()));
observations.stream()
.filter(o -> o.getObservationTimeSeriesId() != null)
.forEach(o -> o.setObservationTimeSeries(timeSeriesMap.get(o.getObservationTimeSeriesId())));
return observations;
}
private List<Observation> getObservationsWithObservers(List<Observation> observations) { private List<Observation> getObservationsWithObservers(List<Observation> observations) {
Set<Integer> userIds = new HashSet<>(); Set<Integer> userIds = new HashSet<>();
observations.stream().filter((o) -> (o.getUserId() != null)).forEach((o) -> { observations.stream().filter((o) -> (o.getUserId() != null)).forEach((o) -> {
userIds.add(o.getUserId()); userIds.add(o.getUserId());
}); });
// Nothing to do? // Nothing to do?
if(userIds.isEmpty()) if (userIds.isEmpty()) {
{
return observations; return observations;
} }
List<VipsLogicUser> users = userBean.getUsers(userIds); List<VipsLogicUser> users = userBean.getUsers(userIds);
Map<Integer, VipsLogicUser> mappedUsers = new HashMap<>(); Map<Integer, VipsLogicUser> mappedUsers = new HashMap<>();
users.stream().forEach((user) -> { users.stream().forEach((user) -> {
mappedUsers.put(user.getUserId(), user); mappedUsers.put(user.getUserId(), user);
}); });
observations.stream().filter((o) -> (o.getUserId() != null)).forEach((o) -> { observations.stream().filter((o) -> (o.getUserId() != null)).forEach((o) -> {
o.setUser(mappedUsers.get(o.getUserId())); o.setUser(mappedUsers.get(o.getUserId()));
}); });
return observations; return observations;
} }
public List<Observation> getObservationsOfPest(Integer pestOrganismId) public List<Observation> getObservationsOfPest(Integer pestOrganismId) {
{ List<Observation> observations =
List <Observation> observations = em.createNamedQuery("Observation.findByOrganism")
em.createNamedQuery("Observation.findByOrganism") .setParameter("organism", em.find(Organism.class, pestOrganismId))
.setParameter("organism", em.find(Organism.class, pestOrganismId)) .getResultList();
.getResultList();
observations = this.getObservationsWithGeoInfo(observations); observations = this.getObservationsWithGeoInfo(observations);
observations = this.getObservationsWithLocations(observations); observations = this.getObservationsWithLocations(observations);
observations = getObservationsWithObservers(observations); observations = getObservationsWithObservers(observations);
return observations; return observations;
} }
public List<Observation> getObservationsOfPestForUser(VipsLogicUser user, Integer pestOrganismId) public List<Observation> getObservationsOfPestForUser(VipsLogicUser user, Integer pestOrganismId) {
{ List<Observation> observations =
List <Observation> observations = em.createNamedQuery("Observation.findByUserIdAndOrganism")
em.createNamedQuery("Observation.findByUserIdAndOrganism") .setParameter("userId", user.getUserId())
.setParameter("userId", user.getUserId()) .setParameter("organism", em.find(Organism.class, pestOrganismId))
.setParameter("organism", em.find(Organism.class, pestOrganismId)) .getResultList();
.getResultList();
observations = this.getObservationsWithGeoInfo(observations); observations = this.getObservationsWithGeoInfo(observations);
observations = this.getObservationsWithLocations(observations); observations = this.getObservationsWithLocations(observations);
observations = this.getObservationsWithObservers(observations); observations = this.getObservationsWithObservers(observations);
...@@ -604,98 +588,99 @@ public class ObservationBean { ...@@ -604,98 +588,99 @@ public class ObservationBean {
} }
public List<Observation> getFilteredObservations( public List<Observation> getFilteredObservations(
Integer organizationId, Integer organizationId,
Integer pestId, Integer observationTimeSeriesId,
Integer cropId, Integer pestId,
Integer cropId,
List<Integer> cropCategoryId, List<Integer> cropCategoryId,
Date from, Date from,
Date to, Date to,
Boolean isPositive Boolean isPositive) {
)
{
// The minimum SQL // The minimum SQL
String sql = "SELECT * FROM public.observation \n" + String sql = "SELECT * FROM public.observation \n" +
"WHERE status_type_id = :statusTypeId \n " + "WHERE status_type_id = :statusTypeId \n " +
"AND user_id IN (SELECT user_id FROM public.vips_logic_user WHERE organization_id = :organizationId) \n"; "AND user_id IN (SELECT user_id FROM public.vips_logic_user WHERE organization_id = :organizationId) \n";
Map<String, Object> parameters = new HashMap<>(); Map<String, Object> parameters = new HashMap<>();
parameters.put("statusTypeId", ObservationStatusType.STATUS_APPROVED); parameters.put("statusTypeId", ObservationStatusType.STATUS_APPROVED);
parameters.put("organizationId", organizationId); parameters.put("organizationId", organizationId);
// Filter for observation time series
if (observationTimeSeriesId != null && observationTimeSeriesId > 0) {
sql += "AND observation_time_series_id = :observationTimeSeriesId \n";
parameters.put("observationTimeSeriesId", observationTimeSeriesId);
}
// Filter for pest // Filter for pest
if(pestId != null && pestId > 0) if (pestId != null && pestId > 0) {
{
sql += "AND organism_id = :organismId \n"; sql += "AND organism_id = :organismId \n";
parameters.put("organismId", pestId); parameters.put("organismId", pestId);
} }
// Filter either for crop or cropCategoryId // Filter either for crop or cropCategoryId
if(cropId != null && cropId > 0) if (cropId != null && cropId > 0) {
{
sql += "AND crop_organism_id = :cropOrganismId \n"; sql += "AND crop_organism_id = :cropOrganismId \n";
parameters.put("cropOrganismId", cropId); parameters.put("cropOrganismId", cropId);
} } else if (cropCategoryId != null && !cropCategoryId.isEmpty()) {
else if(cropCategoryId != null && ! cropCategoryId.isEmpty())
{
List<CropCategory> cropCategories = em.createNamedQuery("CropCategory.findByCropCategoryIds", CropCategory.class) List<CropCategory> cropCategories = em.createNamedQuery("CropCategory.findByCropCategoryIds", CropCategory.class)
.setParameter("cropCategoryIds", cropCategoryId) .setParameter("cropCategoryIds", cropCategoryId)
.getResultList(); .getResultList();
List<Integer> cropIds = new ArrayList(cropCategories.stream().flatMap(cC->Arrays.asList(cC.getCropOrganismIds()).stream()).collect(Collectors.toSet())); List<Integer> cropIds = new ArrayList(cropCategories.stream().flatMap(cC -> cC.getCropOrganismIds().stream()).collect(Collectors.toSet()));
sql += "AND crop_organism_id IN (:cropOrganismIds) \n"; sql += "AND crop_organism_id IN (:cropOrganismIds) \n";
parameters.put("cropOrganismIds", cropIds); parameters.put("cropOrganismIds", cropIds);
//parameters.put("cropOrganismIds", List.of(5));
} }
// Filter for dates // Filter for dates
if(from != null) if (from != null) {
{
sql += "AND time_of_observation >= :from \n"; sql += "AND time_of_observation >= :from \n";
parameters.put("from", from); parameters.put("from", from);
} }
if(to != null) if (to != null) {
{
sql += "AND time_of_observation <= :to \n"; sql += "AND time_of_observation <= :to \n";
parameters.put("to", to); parameters.put("to", to);
} }
// Filter for positive/negative registrations // Filter for positive/negative registrations
if(isPositive != null) if (isPositive != null) {
{
sql += "AND is_positive = :isPositive \n"; sql += "AND is_positive = :isPositive \n";
parameters.put("isPositive", isPositive); parameters.put("isPositive", isPositive);
} }
sql += "ORDER BY time_of_observation DESC, observation_id DESC";
LOGGER.debug(sql); LOGGER.debug(sql);
Query q = em.createNativeQuery(sql, Observation.class); Query q = em.createNativeQuery(sql, Observation.class);
// Setting the parameters one by one // Setting the parameters one by one
parameters.keySet().stream().forEach( parameters.keySet().stream().forEach(
(key)->{LOGGER.debug(key + ": " + parameters.get(key)); q.setParameter(key, parameters.get(key));} (key) -> {
LOGGER.debug(key + ": " + parameters.get(key));
q.setParameter(key, parameters.get(key));
}
); );
//Date start = new Date(); //Date start = new Date();
List<Observation> observations = q.getResultList(); List<Observation> observations = q.getResultList();
//System.out.println("Finding obs took " + (new Date().getTime() - start.getTime()) + " milliseconds"); //System.out.println("Finding obs took " + (new Date().getTime() - start.getTime()) + " milliseconds");
//start = new Date(); //start = new Date();
observations.stream().forEach( observations.stream().forEach(
(observation)->observation.setUser(em.find(VipsLogicUser.class, observation.getUserId())) (observation) -> observation.setUser(em.find(VipsLogicUser.class, observation.getUserId()))
); );
//System.out.println("Finding users took " + (new Date().getTime() - start.getTime()) + " milliseconds"); //System.out.println("Finding users took " + (new Date().getTime() - start.getTime()) + " milliseconds");
List<Observation> retVal = new ArrayList<>(); List<Observation> retVal = new ArrayList<>();
if(! observations.isEmpty()) if (!observations.isEmpty()) {
{
//Date start = new Date(); //Date start = new Date();
retVal = this.getObservationsWithGeoInfo(observations); retVal = this.getObservationsWithGeoInfo(observations);
//System.out.println("Finding geoinfo took " + (new Date().getTime() - start.getTime()) + " milliseconds"); //System.out.println("Finding geoinfo took " + (new Date().getTime() - start.getTime()) + " milliseconds");
//start = new Date(); //start = new Date();
retVal = this.getObservationsWithLocations(retVal); retVal = this.getObservationsWithLocations(retVal);
//System.out.println("Finding locations took " + (new Date().getTime() - start.getTime()) + " milliseconds"); //System.out.println("Finding locations took " + (new Date().getTime() - start.getTime()) + " milliseconds");
retVal = this.getObservationsWithTimeSeries(retVal);
} }
return retVal; return retVal;
} }
public List<Organism> getObservedPests(Integer organizationId) { public List<Organism> getObservedPests(Integer organizationId) {
...@@ -706,9 +691,9 @@ public class ObservationBean { ...@@ -706,9 +691,9 @@ public class ObservationBean {
return em.createNamedQuery("Organism.findByOrganismIds") return em.createNamedQuery("Organism.findByOrganismIds")
.setParameter("organismIds", pestIds) .setParameter("organismIds", pestIds)
.getResultList(); .getResultList();
} }
public List<Organism> getObservedCrops(Integer organizationId) { public List<Organism> getObservedCrops(Integer organizationId) {
Query q = em.createNativeQuery("SELECT DISTINCT crop_organism_id FROM public.observation WHERE user_id IN (" Query q = em.createNativeQuery("SELECT DISTINCT crop_organism_id FROM public.observation WHERE user_id IN ("
+ " SELECT user_id FROM vips_logic_user WHERE organization_id = :organizationId" + " SELECT user_id FROM vips_logic_user WHERE organization_id = :organizationId"
...@@ -717,7 +702,7 @@ public class ObservationBean { ...@@ -717,7 +702,7 @@ public class ObservationBean {
return em.createNamedQuery("Organism.findByOrganismIds") return em.createNamedQuery("Organism.findByOrganismIds")
.setParameter("organismIds", cropIds) .setParameter("organismIds", cropIds)
.getResultList(); .getResultList();
} }
public Observation getObservationFromGeoJSON(String geoJSON) throws IOException { public Observation getObservationFromGeoJSON(String geoJSON) throws IOException {
...@@ -727,23 +712,22 @@ public class ObservationBean { ...@@ -727,23 +712,22 @@ public class ObservationBean {
Map<String, Object> properties = firstAndBest.getProperties(); Map<String, Object> properties = firstAndBest.getProperties();
Observation observation = new Observation(); Observation observation = new Observation();
Integer observationId = (Integer) properties.get("observationId"); Integer observationId = (Integer) properties.get("observationId");
if(observationId > 0) if (observationId > 0) {
{
observation = em.find(Observation.class, observationId); observation = em.find(Observation.class, observationId);
} }
observation.setObservationData((String) properties.get("observationData")); observation.setObservationData((String) properties.get("observationData"));
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
observation.setCropOrganism(mapper.convertValue(properties.get("cropOrganism"), Organism.class)); observation.setCropOrganism(mapper.convertValue(properties.get("cropOrganism"), Organism.class));
observation.setOrganism(mapper.convertValue(properties.get("organism"), Organism.class)); observation.setOrganism(mapper.convertValue(properties.get("organism"), Organism.class));
observation.setObservationHeading((String)properties.get("observationHeading")); observation.setObservationHeading((String) properties.get("observationHeading"));
observation.setObservationText((String)properties.get("observationText")); observation.setObservationText((String) properties.get("observationText"));
observation.setTimeOfObservation(new Date((Long) properties.get("timeOfObservation"))); observation.setTimeOfObservation(new Date((Long) properties.get("timeOfObservation")));
observation.setGeoinfo(geoJSON); observation.setGeoinfo(geoJSON);
observation.setStatusTypeId((Integer) properties.get("statusTypeId")); observation.setStatusTypeId((Integer) properties.get("statusTypeId"));
observation.setStatusRemarks((String) properties.get("statusRemarks")); observation.setStatusRemarks((String) properties.get("statusRemarks"));
observation.setIsQuantified((Boolean) properties.get("isQuantified")); observation.setIsQuantified((Boolean) properties.get("isQuantified"));
observation.setBroadcastMessage((Boolean) properties.get("broadcastMessage")); observation.setBroadcastMessage((Boolean) properties.get("broadcastMessage"));
return observation; return observation;
} }
public void deleteGisObservationByGis(Integer gisId) { public void deleteGisObservationByGis(Integer gisId) {
...@@ -759,41 +743,34 @@ public class ObservationBean { ...@@ -759,41 +743,34 @@ public class ObservationBean {
.getResultList(); .getResultList();
} }
public List<Integer> getOrganizationGroupIds(Observation observation) { public List<Integer> getOrganizationGroupIds(Observation observation) {
if(observation.getObservationId() != null) if (observation.getObservationId() != null) {
{
return em.createNativeQuery("SELECT organization_group_id FROM public.organization_group_observation " return em.createNativeQuery("SELECT organization_group_id FROM public.organization_group_observation "
+ "WHERE observation_id = :observationId") + "WHERE observation_id = :observationId")
.setParameter("observationId", observation.getObservationId()) .setParameter("observationId", observation.getObservationId())
.getResultList(); .getResultList();
} } else {
else
{
return new ArrayList<>(); return new ArrayList<>();
} }
} }
public void storeOrganizationGroupObservationIds(Observation obs, String[] organizationGroupIds) { public void storeOrganizationGroupObservationIds(Observation obs, String[] organizationGroupIds) {
// First delete all current group memberships // First delete all current group memberships
em.createNativeQuery("DELETE FROM public.organization_group_observation WHERE observation_id=:observationId") em.createNativeQuery("DELETE FROM public.organization_group_observation WHERE observation_id=:observationId")
.setParameter("observationId", obs.getObservationId()) .setParameter("observationId", obs.getObservationId())
.executeUpdate(); .executeUpdate();
if(organizationGroupIds != null) if (organizationGroupIds != null) {
{
Query q = em.createNativeQuery("INSERT INTO public.organization_group_observation (organization_group_id, observation_id) " Query q = em.createNativeQuery("INSERT INTO public.organization_group_observation (organization_group_id, observation_id) "
+ "VALUES(:organizationGroupId, :observationId)") + "VALUES(:organizationGroupId, :observationId)")
.setParameter("observationId", obs.getObservationId()); .setParameter("observationId", obs.getObservationId());
// Then add // Then add
for(String groupIdStr:organizationGroupIds) for (String groupIdStr : organizationGroupIds) {
{
try { try {
Integer groupId = Integer.valueOf(groupIdStr); Integer groupId = Integer.valueOf(groupIdStr);
q.setParameter("organizationGroupId", groupId); q.setParameter("organizationGroupId", groupId);
q.executeUpdate(); q.executeUpdate();
} } catch (NumberFormatException ex) {
catch(NumberFormatException ex)
{
// Continue // Continue
} }
} }
...@@ -802,30 +779,27 @@ public class ObservationBean { ...@@ -802,30 +779,27 @@ public class ObservationBean {
/** /**
* Returns the first time an observation of the given pest registered in the system was made * Returns the first time an observation of the given pest registered in the system was made
*
* @param organismId * @param organismId
* @return * @return
*/ */
public Date getFirstObservationTime(Integer organismId) { public Date getFirstObservationTime(Integer organismId) {
try try {
{ List<Observation> obs = em.createNamedQuery("Observation.findFirstByOrganism")
List<Observation> obs = em.createNamedQuery("Observation.findFirstByOrganism")
.setParameter("organism", em.find(Organism.class, organismId)) .setParameter("organism", em.find(Organism.class, organismId))
.getResultList(); .getResultList();
return obs.get(0).getTimeOfObservation(); return obs.get(0).getTimeOfObservation();
} } catch (NoResultException | IndexOutOfBoundsException ex) {
catch(NoResultException | IndexOutOfBoundsException ex)
{
return null; return null;
} }
} }
public PolygonService getPolygonService(Integer polygonServiceId) public PolygonService getPolygonService(Integer polygonServiceId) {
{ return em.find(PolygonService.class, polygonServiceId);
return em.find(PolygonService.class, polygonServiceId);
} }
public List<PolygonService> getPolygonServicesForOrganization(Integer organizationId) { public List<PolygonService> getPolygonServicesForOrganization(Integer organizationId) {
return em.createNativeQuery("SELECT * FROM polygon_service p WHERE p.polygon_service_id IN (SELECT polygon_service_id FROM public.organization_polygon_service WHERE organization_id=:organizationId)", PolygonService.class) return em.createNativeQuery("SELECT * FROM polygon_service p WHERE p.polygon_service_id IN (SELECT polygon_service_id FROM public.organization_polygon_service WHERE organization_id=:organizationId)", PolygonService.class)
.setParameter("organizationId", organizationId) .setParameter("organizationId", organizationId)
...@@ -840,7 +814,8 @@ public class ObservationBean { ...@@ -840,7 +814,8 @@ public class ObservationBean {
/** /**
* Part of the cleaning up dependencies procedure for when deleting a POI * Part of the cleaning up dependencies procedure for when deleting a POI
* @param poi *
* @param poi
*/ */
public void deleteObservationsForLocation(PointOfInterest poi) { public void deleteObservationsForLocation(PointOfInterest poi) {
em.createNamedQuery("Observation.findByLocationPointOfInterestId", Observation.class) em.createNamedQuery("Observation.findByLocationPointOfInterestId", Observation.class)
...@@ -848,99 +823,96 @@ public class ObservationBean { ...@@ -848,99 +823,96 @@ public class ObservationBean {
.getResultList().stream() .getResultList().stream()
.forEach(obs -> em.remove(obs)); .forEach(obs -> em.remove(obs));
} }
public void deleteObservationsForObservationTimeSeries(ObservationTimeSeries observationTimeSeries) {
em.createNamedQuery("Observation.findByObservationTimeSeries", Observation.class)
.setParameter("observationTimeSeries", observationTimeSeries)
.getResultList()
.forEach(obs -> em.remove(obs));
}
/** /**
* Returns the appropriate observation data schema * Returns the appropriate observation data schema
* If no existing schema, returns the standard (Requring just a number) * If no existing schema, returns the standard (Requring just a number)
*
* @param organizationId * @param organizationId
* @param organismId * @param organismId
* @param httpServletRequest * @return
* @return
*/ */
public ObservationDataSchema getObservationDataSchema(Integer organizationId, Integer organismId) public ObservationDataSchema getObservationDataSchema(Integer organizationId, Integer organismId) {
{ try {
try
{
return em.createNamedQuery("ObservationDataSchema.findByPK", ObservationDataSchema.class) return em.createNamedQuery("ObservationDataSchema.findByPK", ObservationDataSchema.class)
.setParameter("organizationId", organizationId) .setParameter("organizationId", organizationId)
.setParameter("organismId", organismId) .setParameter("organismId", organismId)
.getSingleResult(); .getSingleResult();
} } catch (NoResultException ex) {
catch(NoResultException ex)
{
//System.out.println("Could not find schema for orgId " + organizationId + " and organismId " + organismId); //System.out.println("Could not find schema for orgId " + organizationId + " and organismId " + organismId);
return this.getStandardSchema(organizationId); return this.getStandardSchema(organizationId);
} }
} }
/** /**
* If there exist title translations for this schema, it * If there exist title translations for this schema, it
*
* @param schema * @param schema
* @param httpServletRequest * @param httpServletRequest
* @return * @return
*/ */
public ObservationDataSchema getLocalizedObservationDataSchema(ObservationDataSchema ods, HttpServletRequest httpServletRequest, ULocale locale) throws IOException public ObservationDataSchema getLocalizedObservationDataSchema(ObservationDataSchema ods, HttpServletRequest httpServletRequest, ULocale locale) throws IOException {
{ if (locale != null) {
if(locale != null) SessionLocaleUtil.setCurrentLocale(httpServletRequest, locale);
{
SessionLocaleUtil.setCurrentLocale(httpServletRequest, locale);
} }
ResourceBundle bundle = SessionLocaleUtil.getI18nBundle(httpServletRequest); ResourceBundle bundle = SessionLocaleUtil.getI18nBundle(httpServletRequest);
// We iterate the schema, replacing default field labels with // We iterate the schema, replacing default field labels with
// translated ones // translated ones
// First: Convert to Jackson JsonNode tree // First: Convert to Jackson JsonNode tree
ObjectMapper m = new ObjectMapper(); ObjectMapper m = new ObjectMapper();
JsonNode rootNode = m.readTree(ods.getDataSchema()); JsonNode rootNode = m.readTree(ods.getDataSchema());
// Is this the full schema or just the "properties" property? // Is this the full schema or just the "properties" property?
JsonNode propertiesNode = rootNode.get("properties") == null ? rootNode : rootNode.get("properties"); JsonNode propertiesNode = rootNode.get("properties") == null ? rootNode : rootNode.get("properties");
Iterator<Entry<String, JsonNode>> nodeIterator = propertiesNode.fields(); Iterator<Entry<String, JsonNode>> nodeIterator = propertiesNode.fields();
String fieldKeyPrefix = "observationDataField_"; String fieldKeyPrefix = "observationDataField_";
// Loop through each field // Loop through each field
while (nodeIterator.hasNext()) { while (nodeIterator.hasNext()) {
Map.Entry<String, JsonNode> schemaPropertyField = (Map.Entry<String, JsonNode>) nodeIterator.next(); Map.Entry<String, JsonNode> schemaPropertyField = (Map.Entry<String, JsonNode>) nodeIterator.next();
// Get the property field key (e.g. "counting2") // Get the property field key (e.g. "counting2")
String fieldKey = schemaPropertyField.getKey(); String fieldKey = schemaPropertyField.getKey();
// Find a translation. // Find a translation.
if(bundle.containsKey(fieldKeyPrefix + fieldKey)) if (bundle.containsKey(fieldKeyPrefix + fieldKey)) {
{ // If found, replace with translation
// If found, replace with translation // Get the property field (e.g. {"title":"Counting 2"} )
// Get the property field (e.g. {"title":"Counting 2"} ) JsonNode schemaProperty = schemaPropertyField.getValue();
JsonNode schemaProperty = schemaPropertyField.getValue(); ((ObjectNode) schemaProperty).put("title", bundle.getString(fieldKeyPrefix + fieldKey));
((ObjectNode)schemaProperty).put("title", bundle.getString(fieldKeyPrefix + fieldKey)); ((ObjectNode) propertiesNode).replace(fieldKey, schemaProperty);
((ObjectNode)propertiesNode).replace(fieldKey, schemaProperty);
}
}
// I repeat: Is this the full schema or just the "properties" property?
if(rootNode.get("properties") != null)
{
((ObjectNode)rootNode).replace("properties", propertiesNode);
}
else
{
rootNode = propertiesNode;
} }
ods.setDataSchema(m.writeValueAsString(rootNode)); }
return ods;
// I repeat: Is this the full schema or just the "properties" property?
if (rootNode.get("properties") != null) {
((ObjectNode) rootNode).replace("properties", propertiesNode);
} else {
rootNode = propertiesNode;
}
ods.setDataSchema(m.writeValueAsString(rootNode));
return ods;
} }
/** /**
*
* @param organizationId * @param organizationId
* @return * @return
*/ */
private ObservationDataSchema getStandardSchema(Integer organizationId){ private ObservationDataSchema getStandardSchema(Integer organizationId) {
ObservationDataSchema retVal = new ObservationDataSchema(); ObservationDataSchema retVal = new ObservationDataSchema();
retVal.setDataSchema("{\n" retVal.setDataSchema("{\n"
+ " \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n" + " \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n"
+ " \"type\": \"object\",\n" + " \"type\": \"object\",\n"
+ " \"title\": \"Default schema\",\n" + " \"title\": \"Default schema\",\n"
+ " \"properties\": {" + " \"properties\": {"
+ "\"number\":{\"title\":\"Number\"}," + "\"number\":{\"title\":\"Number\"},"
+ "\"unit\":{\"title\":\"Unit\"}" + "\"unit\":{\"title\":\"Unit\"}"
+ "}" + "}"
...@@ -955,7 +927,6 @@ public class ObservationBean { ...@@ -955,7 +927,6 @@ public class ObservationBean {
retVal.setObservationDataSchemaPK(pk); retVal.setObservationDataSchemaPK(pk);
return retVal; return retVal;
} }
} }
/*
* Copyright (c) 2018 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 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/>.
*
*/
package no.nibio.vips.logic.controller.session;
import java.util.*;
import jakarta.ejb.EJB;
import jakarta.ejb.Stateless;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import no.nibio.vips.logic.entity.ObservationTimeSeries;
import no.nibio.vips.logic.entity.PointOfInterest;
import no.nibio.vips.logic.entity.VipsLogicUser;
@Stateless
public class ObservationTimeSeriesBean {
@PersistenceContext(unitName = "VIPSLogic-PU")
EntityManager em;
@EJB
PointOfInterestBean pointOfInterestBean;
@EJB
UserBean userBean;
@EJB
ObservationBean observationBean;
public List<ObservationTimeSeries> getObservationTimeSeriesListForUser(VipsLogicUser user) {
List<ObservationTimeSeries> resultList = em.createNamedQuery("ObservationTimeSeries.findByUserId", ObservationTimeSeries.class)
.setParameter("userId", user.getUserId())
.getResultList();
this.enrichObservationTimeSeriesListWithPointOfInterest(resultList);
this.enrichObservationTimeSeriesListWithObservers(resultList);
return resultList;
}
/**
* Get observation time series with given id. Enrich object with user information before returning.
* @param observationTimeSeriesId the id of the observation time series to retrieve
* @return the observation time series with the given id
*/
public ObservationTimeSeries getObservationTimeSeries(Integer observationTimeSeriesId) {
ObservationTimeSeries ots = em.find(ObservationTimeSeries.class, observationTimeSeriesId);
if (ots != null) {
ots.setUser(em.find(VipsLogicUser.class, ots.getUserId()));
if (ots.getLastModifiedBy() != null) {
ots.setLastModifiedByUser(em.find(VipsLogicUser.class, ots.getLastModifiedBy()));
}
}
return ots;
}
public List<ObservationTimeSeries> getObservationTimeSeriesList(Set<Integer> observationTimeSeriesIds) {
return em.createNamedQuery("ObservationTimeSeries.findByObservationTimeSeriesIds")
.setParameter("observationTimeSeriesIds", observationTimeSeriesIds)
.getResultList();
}
/**
* @param ots the observation time series
* @return The merged object
*/
public ObservationTimeSeries storeObservationTimeSeries(ObservationTimeSeries ots) {
return em.merge(ots);
}
public void deleteObservationTimeSeries(Integer id) {
ObservationTimeSeries observationTimeSeries = em.find(ObservationTimeSeries.class, id);
if (observationTimeSeries != null) {
// The app prevents deletion of time series with observations
observationBean.deleteObservationsForObservationTimeSeries(observationTimeSeries);
em.remove(observationTimeSeries);
}
}
/**
* Enrich given list of observation time series with point of interest information
*
* @param otsList The list of observation time series to enrich
*/
public void enrichObservationTimeSeriesListWithPointOfInterest(List<ObservationTimeSeries> otsList) {
Set<Integer> locationPoiIds = new HashSet<>();
otsList.stream().filter((o) -> (o.getLocationPointOfInterestId() != null)).forEach((o) -> {
locationPoiIds.add(o.getLocationPointOfInterestId());
});
if (locationPoiIds.isEmpty()) {
return;
}
List<PointOfInterest> pois = pointOfInterestBean.getPois(locationPoiIds);
Map<Integer, PointOfInterest> mappedPois = new HashMap<>();
pois.stream().forEach((poi) -> {
mappedPois.put(poi.getPointOfInterestId(), poi);
});
otsList.stream().filter((o) -> (o.getLocationPointOfInterestId() != null)).forEach((o) -> {
o.setLocationPointOfInterest(mappedPois.get(o.getLocationPointOfInterestId()));
});
}
/**
* Enrich given observation time series with point of interest information
*
* @param ots The observation time series to enrich
*/
public void enrichObservationTimeSeriesWithPointOfInterest(ObservationTimeSeries ots) {
if (ots == null || ots.getLocationPointOfInterestId() == null) {
return;
}
ots.setLocationPointOfInterest(pointOfInterestBean.getPointOfInterest(ots.getLocationPointOfInterestId()));
}
/**
* Enrich given list of observation time series with user information
*
* @param otsList The list of observation time series to enrich
*/
private void enrichObservationTimeSeriesListWithObservers(List<ObservationTimeSeries> otsList) {
Set<Integer> userIds = new HashSet<>();
otsList.stream().filter((o) -> (o.getUserId() != null)).forEach((o) -> {
userIds.add(o.getUserId());
});
if (userIds.isEmpty()) {
return;
}
List<VipsLogicUser> users = userBean.getUsers(userIds);
Map<Integer, VipsLogicUser> mappedUsers = new HashMap<>();
users.stream().forEach((user) -> {
mappedUsers.put(user.getUserId(), user);
});
otsList.stream().filter((o) -> (o.getUserId() != null)).forEach((o) -> {
o.setUser(mappedUsers.get(o.getUserId()));
});
}
}
...@@ -33,11 +33,11 @@ import java.util.HashSet; ...@@ -33,11 +33,11 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.ejb.Stateless; import jakarta.ejb.Stateless;
import javax.persistence.EntityManager; import jakarta.persistence.EntityManager;
import javax.persistence.NoResultException; import jakarta.persistence.NoResultException;
import javax.persistence.PersistenceContext; import jakarta.persistence.PersistenceContext;
import javax.persistence.Query; import jakarta.persistence.Query;
import no.nibio.vips.logic.entity.CropCategory; import no.nibio.vips.logic.entity.CropCategory;
import no.nibio.vips.logic.entity.CropPest; import no.nibio.vips.logic.entity.CropPest;
import no.nibio.vips.logic.entity.DbUpdate; import no.nibio.vips.logic.entity.DbUpdate;
...@@ -419,7 +419,7 @@ public class OrganismBean { ...@@ -419,7 +419,7 @@ public class OrganismBean {
cropCategories.stream() cropCategories.stream()
.filter((cc) -> (cc.getCropOrganismIds() != null)) .filter((cc) -> (cc.getCropOrganismIds() != null))
.forEachOrdered((cc) -> { .forEachOrdered((cc) -> {
retVal.addAll(Arrays.asList(cc.getCropOrganismIds())); retVal.addAll(cc.getCropOrganismIds());
}); });
return retVal; return retVal;
......
...@@ -33,13 +33,13 @@ import java.util.List; ...@@ -33,13 +33,13 @@ import java.util.List;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.ejb.EJB; import jakarta.ejb.EJB;
import javax.ejb.LocalBean; import jakarta.ejb.LocalBean;
import javax.ejb.Stateless; import jakarta.ejb.Stateless;
import javax.persistence.EntityManager; import jakarta.persistence.EntityManager;
import javax.persistence.NoResultException; import jakarta.persistence.NoResultException;
import javax.persistence.PersistenceContext; import jakarta.persistence.PersistenceContext;
import javax.persistence.Query; import jakarta.persistence.Query;
import no.nibio.vips.gis.GISUtil; import no.nibio.vips.gis.GISUtil;
import no.nibio.vips.logic.entity.ExternalResource; import no.nibio.vips.logic.entity.ExternalResource;
import no.nibio.vips.logic.entity.ExternalResourceType; import no.nibio.vips.logic.entity.ExternalResourceType;
...@@ -263,10 +263,54 @@ public class PointOfInterestBean { ...@@ -263,10 +263,54 @@ public class PointOfInterestBean {
return kml; return kml;
} }
public WeatherStationDataSource getWeatherStationDataSource(Integer weatherStationDataSourceId)
{
return em.find(WeatherStationDataSource.class, weatherStationDataSourceId);
}
public List<WeatherStationDataSource> getWeatherStationDataSources() { public List<WeatherStationDataSource> getWeatherStationDataSources() {
return em.createNamedQuery("WeatherStationDataSource.findAll").getResultList(); return em.createNamedQuery("WeatherStationDataSource.findAll").getResultList();
} }
public List<WeatherStationDataSource> getGridWeatherStationDataSources() {
return em.createNamedQuery("WeatherStationDataSource.findGridSources").getResultList();
}
/**
* Checks if the weather station data source can be deleted from the system. Criteria:
* <ul>
* <li>Not referenced from public.point_of_interest_weather_station</li>
* <li>Not referenced from public.organization</li>
* </ul>
* @param weatherStationDataSource
* @return
*/
public Boolean isweatherStationDataSourceDeleteable(WeatherStationDataSource weatherStationDataSource)
{
Query poiRefQuery = em.createQuery("SELECT COUNT(*) FROM PointOfInterestWeatherStation poiws where poiws.weatherStationDataSourceId = :weatherStationDataSourceId");
Long weatherStationReferences = (Long) poiRefQuery.setParameter("weatherStationDataSourceId", weatherStationDataSource).getSingleResult();
if(weatherStationReferences > 0)
{
return false;
}
Query orgRefQuery = em.createQuery("SELECT COUNT(*) FROM Organization o where o.defaultGridWeatherStationDataSource = :weatherStationDataSourceId");
Long organizationReferences = (Long) orgRefQuery.setParameter("weatherStationDataSourceId", weatherStationDataSource).getSingleResult();
return organizationReferences == 0;
}
public void deleteWeatherStationDataSource(WeatherStationDataSource weatherStationDataSource)
{
WeatherStationDataSource sourceToDelete = em.find(WeatherStationDataSource.class, weatherStationDataSource.getWeatherStationDataSourceId());
em.remove(sourceToDelete);
}
public WeatherStationDataSource storeWeatherStationDataSource(WeatherStationDataSource weatherStationDataSource)
{
weatherStationDataSource = em.merge(weatherStationDataSource);
return weatherStationDataSource;
}
public PointOfInterestWeatherStation storeWeatherStation(PointOfInterestWeatherStation weatherStation) { public PointOfInterestWeatherStation storeWeatherStation(PointOfInterestWeatherStation weatherStation) {
weatherStation = em.merge(weatherStation); weatherStation = em.merge(weatherStation);
return weatherStation; return weatherStation;
......
...@@ -37,16 +37,16 @@ import java.util.Set; ...@@ -37,16 +37,16 @@ import java.util.Set;
import java.util.SortedMap; import java.util.SortedMap;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.TreeMap; import java.util.TreeMap;
import javax.ejb.EJB; import jakarta.ejb.EJB;
import javax.ejb.Stateless; import jakarta.ejb.Stateless;
import javax.persistence.EntityManager; import jakarta.persistence.EntityManager;
import javax.persistence.PersistenceContext; import jakarta.persistence.PersistenceContext;
import javax.persistence.Query; import jakarta.persistence.Query;
import javax.ws.rs.client.Client; import jakarta.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder; import jakarta.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget; import jakarta.ws.rs.client.WebTarget;
import javax.ws.rs.core.GenericType; import jakarta.ws.rs.core.GenericType;
import javax.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
import no.nibio.vips.coremanager.service.ManagerResource; import no.nibio.vips.coremanager.service.ManagerResource;
import no.nibio.vips.entity.ModelConfiguration; import no.nibio.vips.entity.ModelConfiguration;
import no.nibio.vips.entity.ModelRunRequest; import no.nibio.vips.entity.ModelRunRequest;
...@@ -217,9 +217,6 @@ public class SchedulingBean { ...@@ -217,9 +217,6 @@ public class SchedulingBean {
sendForecastNotificationsCollector.getTasks().add(morningAndAfternoonPattern, VipsLogicTaskFactory.createVipsLogicTask(VipsLogicTaskFactory.SEND_FORECAST_EVENT_NOTIFICATIONS_TASK)); sendForecastNotificationsCollector.getTasks().add(morningAndAfternoonPattern, VipsLogicTaskFactory.createVipsLogicTask(VipsLogicTaskFactory.SEND_FORECAST_EVENT_NOTIFICATIONS_TASK));
// Run grid models
VIPSLogicTaskCollector runGridModelsCollector = new VIPSLogicTaskCollector(-1);
runGridModelsCollector.getTasks().add(morningAndAfternoonPattern, VipsLogicTaskFactory.createVipsLogicTask(VipsLogicTaskFactory.RUN_GRID_MODELS_TASK));
List<TaskCollector> definedTasks = new ArrayList<>(); List<TaskCollector> definedTasks = new ArrayList<>();
definedTasks.add(modelRunCollector); definedTasks.add(modelRunCollector);
...@@ -227,7 +224,6 @@ public class SchedulingBean { ...@@ -227,7 +224,6 @@ public class SchedulingBean {
definedTasks.add(summariesCollector); definedTasks.add(summariesCollector);
definedTasks.add(deleteAllExpiredUserUuidsCollector); definedTasks.add(deleteAllExpiredUserUuidsCollector);
definedTasks.add(sendForecastNotificationsCollector); definedTasks.add(sendForecastNotificationsCollector);
definedTasks.add(runGridModelsCollector);
return definedTasks; return definedTasks;
} }
......
...@@ -26,7 +26,7 @@ import no.nibio.vips.logic.messaging.MessagingBean; ...@@ -26,7 +26,7 @@ import no.nibio.vips.logic.messaging.MessagingBean;
/** /**
* Thought this was oblivious because of @EJB, but it turns out this is necessary when invoking beans from outside managed beans! * Thought this was oblivious because of @EJB, but it turns out this is necessary when invoking beans from outside managed beans!
* @copyright 2013-2022 <a href="http://www.nibio.no/">NIBIO</a> * @copyright 2013-2025 <a href="http://www.nibio.no/">NIBIO</a>
* @author Tor-Einar Skog <tor-einar.skog@nibio.no> * @author Tor-Einar Skog <tor-einar.skog@nibio.no>
*/ */
...@@ -34,7 +34,7 @@ public class SessionControllerGetter { ...@@ -34,7 +34,7 @@ public class SessionControllerGetter {
// This obviously has to be changed when changing the application name in Maven // This obviously has to be changed when changing the application name in Maven
// TODO: Refactor out to System properties (e.g. in standalone.xml in JBoss/WildFly) // TODO: Refactor out to System properties (e.g. in standalone.xml in JBoss/WildFly)
public static final String JNDI_PATH = "java:global/VIPSLogic-2024.1/"; public static final String JNDI_PATH = "java:global/VIPSLogic-2025.1/";
public static SchedulingBean getSchedulingBean() public static SchedulingBean getSchedulingBean()
{ {
......
...@@ -41,14 +41,14 @@ import java.util.Set; ...@@ -41,14 +41,14 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.ejb.EJB; import jakarta.ejb.EJB;
import javax.ejb.LocalBean; import jakarta.ejb.LocalBean;
import javax.ejb.Stateless; import jakarta.ejb.Stateless;
import javax.persistence.*; import jakarta.persistence.*;
import javax.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation; import jakarta.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException; import jakarta.validation.ConstraintViolationException;
import javax.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.HttpHeaders;
import no.nibio.vips.logic.authenticate.PasswordValidationException; import no.nibio.vips.logic.authenticate.PasswordValidationException;
import no.nibio.vips.logic.entity.*; import no.nibio.vips.logic.entity.*;
......
...@@ -21,19 +21,19 @@ package no.nibio.vips.logic.entity; ...@@ -21,19 +21,19 @@ package no.nibio.vips.logic.entity;
import java.io.Serializable; import java.io.Serializable;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
import javax.persistence.Basic; import jakarta.persistence.Basic;
import javax.persistence.Column; import jakarta.persistence.Column;
import javax.persistence.Entity; import jakarta.persistence.Entity;
import javax.persistence.Id; import jakarta.persistence.Id;
import javax.persistence.JoinColumn; import jakarta.persistence.JoinColumn;
import javax.persistence.JoinTable; import jakarta.persistence.JoinTable;
import javax.persistence.ManyToMany; import jakarta.persistence.ManyToMany;
import javax.persistence.NamedQueries; import jakarta.persistence.NamedQueries;
import javax.persistence.NamedQuery; import jakarta.persistence.NamedQuery;
import javax.persistence.OneToMany; import jakarta.persistence.OneToMany;
import javax.persistence.Table; import jakarta.persistence.Table;
import javax.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import javax.validation.constraints.Size; import jakarta.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.XmlTransient;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
......
...@@ -19,27 +19,28 @@ ...@@ -19,27 +19,28 @@
package no.nibio.vips.logic.entity; package no.nibio.vips.logic.entity;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import io.hypersistence.utils.hibernate.type.array.ListArrayType;
import java.io.Serializable; import java.io.Serializable;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import javax.persistence.Basic; import java.util.stream.Collectors;
import javax.persistence.CascadeType; import jakarta.persistence.Basic;
import javax.persistence.Column; import jakarta.persistence.CascadeType;
import javax.persistence.Entity; import jakarta.persistence.Column;
import javax.persistence.FetchType; import jakarta.persistence.Entity;
import javax.persistence.Id; import jakarta.persistence.FetchType;
import javax.persistence.NamedQueries; import jakarta.persistence.Id;
import javax.persistence.NamedQuery; import jakarta.persistence.NamedQueries;
import javax.persistence.OneToMany; import jakarta.persistence.NamedQuery;
import javax.persistence.Table; import jakarta.persistence.OneToMany;
import javax.validation.constraints.NotNull; import jakarta.persistence.Table;
import javax.validation.constraints.Size; import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import no.nibio.vips.logic.util.IntegerArrayUserType;
import org.hibernate.annotations.Type; import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.hibernate.annotations.TypeDefs;
/** /**
* @copyright 2016 <a href="http://www.nibio.no/">NIBIO</a> * @copyright 2016 <a href="http://www.nibio.no/">NIBIO</a>
...@@ -48,7 +49,6 @@ import org.hibernate.annotations.TypeDefs; ...@@ -48,7 +49,6 @@ import org.hibernate.annotations.TypeDefs;
@Entity @Entity
@Table(name = "crop_category") @Table(name = "crop_category")
@XmlRootElement @XmlRootElement
@TypeDefs( {@TypeDef( name= "IntegerArray", typeClass = IntegerArrayUserType.class)})
@NamedQueries({ @NamedQueries({
@NamedQuery(name = "CropCategory.findAll", query = "SELECT c FROM CropCategory c"), @NamedQuery(name = "CropCategory.findAll", query = "SELECT c FROM CropCategory c"),
@NamedQuery(name = "CropCategory.findByCropCategoryId", query = "SELECT c FROM CropCategory c WHERE c.cropCategoryId = :cropCategoryId"), @NamedQuery(name = "CropCategory.findByCropCategoryId", query = "SELECT c FROM CropCategory c WHERE c.cropCategoryId = :cropCategoryId"),
...@@ -70,9 +70,9 @@ public class CropCategory implements Serializable { ...@@ -70,9 +70,9 @@ public class CropCategory implements Serializable {
private String defaultName; private String defaultName;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "cropCategoryId", fetch = FetchType.EAGER) @OneToMany(cascade = CascadeType.ALL, mappedBy = "cropCategoryId", fetch = FetchType.EAGER)
private Set<CropCategoryLocal> cropCategoryLocalSet; private Set<CropCategoryLocal> cropCategoryLocalSet;
@Type(type = "IntegerArray")
@Column(name = "crop_organism_ids") @Column(name = "crop_organism_ids")
private Integer[] cropOrganismIds; @Type(ListArrayType.class)
private List<Integer> cropOrganismIds;
@Column(name = "organization_id") @Column(name = "organization_id")
private Integer organizationId; private Integer organizationId;
@Column(name = "max_hierarchy_category_id") @Column(name = "max_hierarchy_category_id")
...@@ -101,11 +101,11 @@ public class CropCategory implements Serializable { ...@@ -101,11 +101,11 @@ public class CropCategory implements Serializable {
this.defaultName = defaultName; this.defaultName = defaultName;
} }
public Integer[] getCropOrganismIds() { public List<Integer> getCropOrganismIds() {
return cropOrganismIds; return cropOrganismIds;
} }
public void setCropOrganismIds(Integer[] cropOrganismIds) { public void setCropOrganismIds(List<Integer> cropOrganismIds) {
this.cropOrganismIds = cropOrganismIds; this.cropOrganismIds = cropOrganismIds;
} }
...@@ -203,18 +203,18 @@ public class CropCategory implements Serializable { ...@@ -203,18 +203,18 @@ public class CropCategory implements Serializable {
} }
else else
{ {
cropSet = new HashSet<>(Arrays.asList(this.getCropOrganismIds())); cropSet = new HashSet<>(this.getCropOrganismIds());
} }
cropSet.add(organismId); cropSet.add(organismId);
this.setCropOrganismIds(cropSet.toArray(new Integer[cropSet.size()])); this.setCropOrganismIds(cropSet.stream().collect(Collectors.toList()));
} }
public void removeCropOrganismId(Integer organismId) { public void removeCropOrganismId(Integer organismId) {
if(this.getCropOrganismIds() != null) if(this.getCropOrganismIds() != null)
{ {
Set<Integer> cropSet = new HashSet<>(Arrays.asList(this.getCropOrganismIds())); Set<Integer> cropSet = new HashSet<>(this.getCropOrganismIds());
cropSet.remove(organismId); cropSet.remove(organismId);
this.setCropOrganismIds(cropSet.toArray(new Integer[cropSet.size()])); this.setCropOrganismIds(cropSet.stream().collect(Collectors.toList()));
} }
} }
......
...@@ -19,13 +19,13 @@ ...@@ -19,13 +19,13 @@
package no.nibio.vips.logic.entity; package no.nibio.vips.logic.entity;
import java.io.Serializable; import java.io.Serializable;
import javax.persistence.Column; import jakarta.persistence.Column;
import javax.persistence.EmbeddedId; import jakarta.persistence.EmbeddedId;
import javax.persistence.Entity; import jakarta.persistence.Entity;
import javax.persistence.NamedQueries; import jakarta.persistence.NamedQueries;
import javax.persistence.NamedQuery; import jakarta.persistence.NamedQuery;
import javax.persistence.Table; import jakarta.persistence.Table;
import javax.validation.constraints.Size; import jakarta.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
/** /**
......
...@@ -19,11 +19,11 @@ ...@@ -19,11 +19,11 @@
package no.nibio.vips.logic.entity; package no.nibio.vips.logic.entity;
import java.io.Serializable; import java.io.Serializable;
import javax.persistence.Basic; import jakarta.persistence.Basic;
import javax.persistence.Column; import jakarta.persistence.Column;
import javax.persistence.Embeddable; import jakarta.persistence.Embeddable;
import javax.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import javax.validation.constraints.Size; import jakarta.validation.constraints.Size;
/** /**
* @copyright 2016 <a href="http://www.nibio.no/">NIBIO</a> * @copyright 2016 <a href="http://www.nibio.no/">NIBIO</a>
......
...@@ -19,19 +19,18 @@ ...@@ -19,19 +19,18 @@
package no.nibio.vips.logic.entity; package no.nibio.vips.logic.entity;
import java.io.Serializable; import java.io.Serializable;
import javax.persistence.Basic; import java.util.List;
import javax.persistence.Column; import jakarta.persistence.Basic;
import javax.persistence.Entity; import jakarta.persistence.Column;
import javax.persistence.Id; import jakarta.persistence.Entity;
import javax.persistence.NamedQueries; import jakarta.persistence.Id;
import javax.persistence.NamedQuery; import jakarta.persistence.NamedQueries;
import javax.persistence.Table; import jakarta.persistence.NamedQuery;
import javax.validation.constraints.NotNull; import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import no.nibio.vips.logic.util.IntegerArrayUserType;
import org.hibernate.annotations.Type; import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef; import io.hypersistence.utils.hibernate.type.array.ListArrayType;
import org.hibernate.annotations.TypeDefs;
/** /**
* @copyright 2016 <a href="http://www.nibio.no/">NIBIO</a> * @copyright 2016 <a href="http://www.nibio.no/">NIBIO</a>
...@@ -39,7 +38,6 @@ import org.hibernate.annotations.TypeDefs; ...@@ -39,7 +38,6 @@ import org.hibernate.annotations.TypeDefs;
*/ */
@Entity @Entity
@Table(name = "crop_pest") @Table(name = "crop_pest")
@TypeDefs( {@TypeDef( name= "IntegerArray", typeClass = IntegerArrayUserType.class)})
@XmlRootElement @XmlRootElement
@NamedQueries({ @NamedQueries({
@NamedQuery(name = "CropPest.findAll", query = "SELECT c FROM CropPest c"), @NamedQuery(name = "CropPest.findAll", query = "SELECT c FROM CropPest c"),
...@@ -55,9 +53,9 @@ public class CropPest implements Serializable { ...@@ -55,9 +53,9 @@ public class CropPest implements Serializable {
@NotNull @NotNull
@Column(name = "crop_organism_id") @Column(name = "crop_organism_id")
private Integer cropOrganismId; private Integer cropOrganismId;
@Type(type = "IntegerArray") @Type(ListArrayType.class)
@Column(name = "pest_organism_ids") @Column(name = "pest_organism_ids")
private Integer[] pestOrganismIds; private List<Integer> pestOrganismIds;
@Column(name = "include_all_child_crops") @Column(name = "include_all_child_crops")
private Boolean includeAllChildCrops; private Boolean includeAllChildCrops;
...@@ -76,11 +74,11 @@ public class CropPest implements Serializable { ...@@ -76,11 +74,11 @@ public class CropPest implements Serializable {
this.cropOrganismId = cropOrganismId; this.cropOrganismId = cropOrganismId;
} }
public Integer[] getPestOrganismIds() { public List<Integer> getPestOrganismIds() {
return pestOrganismIds; return pestOrganismIds;
} }
public void setPestOrganismIds(Integer[] pestOrganismIds) { public void setPestOrganismIds(List<Integer> pestOrganismIds) {
this.pestOrganismIds = pestOrganismIds; this.pestOrganismIds = pestOrganismIds;
} }
......
...@@ -20,16 +20,16 @@ package no.nibio.vips.logic.entity; ...@@ -20,16 +20,16 @@ package no.nibio.vips.logic.entity;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collection; import java.util.Collection;
import javax.persistence.Basic; import jakarta.persistence.Basic;
import javax.persistence.Column; import jakarta.persistence.Column;
import javax.persistence.Entity; import jakarta.persistence.Entity;
import javax.persistence.Id; import jakarta.persistence.Id;
import javax.persistence.NamedQueries; import jakarta.persistence.NamedQueries;
import javax.persistence.NamedQuery; import jakarta.persistence.NamedQuery;
import javax.persistence.OneToMany; import jakarta.persistence.OneToMany;
import javax.persistence.Table; import jakarta.persistence.Table;
import javax.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import javax.validation.constraints.Size; import jakarta.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.XmlTransient;
......
...@@ -20,17 +20,17 @@ package no.nibio.vips.logic.entity; ...@@ -20,17 +20,17 @@ package no.nibio.vips.logic.entity;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date; import java.util.Date;
import javax.persistence.Basic; import jakarta.persistence.Basic;
import javax.persistence.Column; import jakarta.persistence.Column;
import javax.persistence.Entity; import jakarta.persistence.Entity;
import javax.persistence.Id; import jakarta.persistence.Id;
import javax.persistence.NamedQueries; import jakarta.persistence.NamedQueries;
import javax.persistence.NamedQuery; import jakarta.persistence.NamedQuery;
import javax.persistence.Table; import jakarta.persistence.Table;
import javax.persistence.Temporal; import jakarta.persistence.Temporal;
import javax.persistence.TemporalType; import jakarta.persistence.TemporalType;
import javax.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import javax.validation.constraints.Size; import jakarta.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
/** /**
......
...@@ -20,21 +20,21 @@ package no.nibio.vips.logic.entity; ...@@ -20,21 +20,21 @@ package no.nibio.vips.logic.entity;
import java.io.Serializable; import java.io.Serializable;
import java.util.Set; import java.util.Set;
import javax.persistence.Basic; import jakarta.persistence.Basic;
import javax.persistence.CascadeType; import jakarta.persistence.CascadeType;
import javax.persistence.Column; import jakarta.persistence.Column;
import javax.persistence.Entity; import jakarta.persistence.Entity;
import javax.persistence.GeneratedValue; import jakarta.persistence.GeneratedValue;
import javax.persistence.GenerationType; import jakarta.persistence.GenerationType;
import javax.persistence.Id; import jakarta.persistence.Id;
import javax.persistence.JoinColumn; import jakarta.persistence.JoinColumn;
import javax.persistence.ManyToMany; import jakarta.persistence.ManyToMany;
import javax.persistence.ManyToOne; import jakarta.persistence.ManyToOne;
import javax.persistence.NamedQueries; import jakarta.persistence.NamedQueries;
import javax.persistence.NamedQuery; import jakarta.persistence.NamedQuery;
import javax.persistence.OneToMany; import jakarta.persistence.OneToMany;
import javax.persistence.Table; import jakarta.persistence.Table;
import javax.validation.constraints.Size; import jakarta.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.XmlTransient;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
......