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;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import javax.ejb.EJB;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.ejb.EJB;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import no.nibio.vips.logic.controller.session.SchedulingBean;
import no.nibio.vips.logic.controller.session.UserBean;
import no.nibio.vips.logic.entity.TaskHistory;
......
......@@ -31,15 +31,15 @@ import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.ejb.EJB;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.PersistenceContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.ejb.EJB;
import jakarta.persistence.EntityManager;
import jakarta.persistence.NoResultException;
import jakarta.persistence.NonUniqueResultException;
import jakarta.persistence.PersistenceContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import no.nibio.vips.i18n.LanguageUtil;
import no.nibio.vips.logic.controller.session.DeleteUserException;
import no.nibio.vips.logic.controller.session.UserBean;
......@@ -51,6 +51,8 @@ import no.nibio.vips.logic.entity.VipsLogicRole;
import no.nibio.vips.logic.entity.VipsLogicUser;
import no.nibio.vips.logic.entity.misc.UserResources;
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.util.ServletUtil;
import no.nibio.web.forms.FormField;
......@@ -71,6 +73,9 @@ public class UserController extends HttpServlet {
@EJB
UserBean userBean;
@EJB
BarkbeetleBean barkbeetleBean;
/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code>
......@@ -406,9 +411,12 @@ public class UserController extends HttpServlet {
Integer userId = Integer.valueOf(request.getParameter("userId"));
VipsLogicUser viewUser = em.find(VipsLogicUser.class, userId);
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(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());
}
......@@ -423,7 +431,9 @@ public class UserController extends HttpServlet {
request.setAttribute("viewUser", viewUser);
request.setAttribute("userResources", userResources);
java.util.Collections.sort(users);
request.setAttribute("users", users);
request.setAttribute("userBarkbeetleSeasonTrapsites", userSeasonTrapsites);
request.setAttribute("errorMsg", request.getParameter("errorMsg"));
request.getRequestDispatcher("/userDeleteForm.ftl").forward(request, response);
}
......@@ -450,7 +460,9 @@ public class UserController extends HttpServlet {
// Are there resources connected to this user?
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;
try
......@@ -460,6 +472,7 @@ public class UserController extends HttpServlet {
if(transferToUser != null)
{
userBean.transferUserResources(viewUser,transferToUser);
barkbeetleBean.transferSeasonTrapsites(viewUser,transferToUser);
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
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
* Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*
*/
package no.nibio.vips.logic.controller.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.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.Data;
import de.micromata.opengis.kml.v_2_2_0.Document;
......@@ -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.Units;
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.entity.ModelConfiguration;
import no.nibio.vips.entity.ModelRunRequest;
......@@ -81,9 +82,6 @@ import no.nibio.vips.logic.util.RunModelException;
import no.nibio.vips.logic.util.SystemTime;
import no.nibio.vips.util.WeatherUtil;
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>
......@@ -94,179 +92,163 @@ public class ForecastBean {
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(ForecastBean.class);
@PersistenceContext(unitName="VIPSLogic-PU")
@PersistenceContext(unitName = "VIPSLogic-PU")
EntityManager em;
@EJB
ForecastBean forecastBean;
@EJB
UserBean userBean;
/**
* Returns all forecast results.
* @return
*
* @return
*/
public List<ForecastResult> getForecastResults()
{
public List<ForecastResult> getForecastResults() {
return em.createNamedQuery("ForecastResult.findAll").getResultList();
}
public List<ForecastResult> getForecastResults(Long forecastConfigurationId)
{
//ForecastConfiguration config = this.getForecastConfiguration(forecastConfigurationId);
public List<ForecastResult> getForecastResults(Long forecastConfigurationId) {
// ForecastConfiguration config = this.getForecastConfiguration(forecastConfigurationId);
Query q = em.createNamedQuery("ForecastResult.findByForecastConfigurationId");
q.setParameter("forecastConfigurationId", forecastConfigurationId);
return q.getResultList();
}
/**
*
* @param forecastConfiguration
* @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
if(!forecastConfiguration.getIsPrivate())
{
if (!forecastConfiguration.getIsPrivate()) {
return true;
}
// 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
ForecastConfiguration fc = em.find(ForecastConfiguration.class, forecastConfigurationId);
if(fc == null)
{
if (fc == null) {
return true;
}
if(fc.getIsPrivate())
{
if(userUUID == null)
{
if (fc.getIsPrivate()) {
if (userUUID == null) {
return false;
}
UUID uUUID = UUID.fromString(userUUID);
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 true;
}
public List<ForecastResult> getForecastResults(Long forecastConfigurationId, Integer latestDays)
{
public List<ForecastResult> getForecastResults(Long forecastConfigurationId, Integer latestDays) {
ForecastResult mostRecentForecastResult = this.getMostRecentForecastResult(forecastConfigurationId);
if(mostRecentForecastResult == null)
{
if (mostRecentForecastResult == null) {
return null;
}
Calendar cal = Calendar.getInstance();
cal.setTime(mostRecentForecastResult.getValidTimeStart());
cal.add(Calendar.DATE, -latestDays);
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");
q.setParameter("forecastConfigurationId", forecastConfigurationId);
q.setParameter("timeStart", timeStart);
q.setParameter("timeEnd", timeEnd);
try
{
try {
return q.getResultList();
}
catch(NoResultException ex)
{
} catch (NoResultException ex) {
return null;
}
}
public ForecastResult getMostRecentForecastResult(Long forecastConfigurationId)
{
public ForecastResult getMostRecentForecastResult(Long forecastConfigurationId) {
Query q = em.createNativeQuery(
"SELECT * FROM forecast_result "
+ "WHERE forecast_configuration_id=:forecastConfigurationId "
+ "AND valid_time_start = ("
+ "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", forecastConfigurationId);
try
{
try {
return (ForecastResult) q.getSingleResult();
}
catch(NoResultException ex)
{
} catch (NoResultException ex) {
return null;
}
}
/**
* Deletes all former results for this forecast configuration, stores the new ones
*
* @param forecastConfiguration
* @param results
* @param results
*/
public void storeResults(ForecastConfiguration forecastConfiguration, List<Result> results)
{
//System.out.println("forecastConfigurationId=" + forecastConfiguration.getForecastConfigurationId());
Query q = em.createNativeQuery("DELETE FROM public.forecast_result WHERE forecast_configuration_id=:forecastConfigurationId");
public void storeResults(ForecastConfiguration forecastConfiguration, List<Result> results) {
// System.out.println("forecastConfigurationId=" + forecastConfiguration.getForecastConfigurationId());
Query q = em.createNativeQuery(
"DELETE FROM public.forecast_result WHERE forecast_configuration_id=:forecastConfigurationId");
q.setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId());
q.executeUpdate();
for(Result result:results)
{
ForecastResult fResult = new ForecastResult(forecastConfiguration.getForecastConfigurationId(),result);
for (Result result : results) {
ForecastResult fResult = new ForecastResult(forecastConfiguration.getForecastConfigurationId(), result);
em.persist(fResult);
}
}
/**
* Get all PUBLIC forecast configurations for one user.
* TODO: Should be season based, or possibly based on start/stop date
* Get all PUBLIC forecast configurations for one user. TODO: Should be season based, or possibly based on
* start/stop date
*
* @param userId
* @return
* @return
*/
public List<ForecastConfiguration> getForecastConfigurationsForUser(Integer userId)
{
public List<ForecastConfiguration> getForecastConfigurationsForUser(Integer userId) {
VipsLogicUser user = em.find(VipsLogicUser.class, userId);
Query q = em.createNamedQuery("ForecastConfiguration.findByVipsLogicUserId");
q.setParameter("vipsLogicUserId", user);
return q.getResultList();
}
/**
* Get all PRIVATE forecast configurations for one user.
* TODO: Should be season based, or possibly based on start/stop date
* Get all PRIVATE forecast configurations for one user. TODO: Should be season based, or possibly based on
* start/stop date
*
* @param userId
* @return
* @return
*/
public List<ForecastConfiguration> getPrivateForecastConfigurationsForUser(Integer userId)
{
public List<ForecastConfiguration> getPrivateForecastConfigurationsForUser(Integer userId) {
VipsLogicUser user = em.find(VipsLogicUser.class, userId);
Query q = em.createNamedQuery("ForecastConfiguration.findPrivateByVipsLogicUserId");
q.setParameter("vipsLogicUserId", user);
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);
Query q = em.createNamedQuery("ForecastConfiguration.findByVipsLogicUserIdAndDate");
q.setParameter("vipsLogicUserId", user);
......@@ -274,17 +256,18 @@ public class ForecastBean {
q.setParameter("to", to);
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);
Query q = em.createNamedQuery("ForecastConfiguration.findByVipsLogicUserIdAndCropOrganismId");
q.setParameter("vipsLogicUserId", user);
q.setParameter("cropOrganismIds", cropOrganismIds);
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);
Query q = em.createNamedQuery("ForecastConfiguration.findByVipsLogicUserIdAndCropOrganismIdsAndDate");
q.setParameter("vipsLogicUserId", user);
......@@ -293,30 +276,28 @@ public class ForecastBean {
q.setParameter("to", to);
return q.getResultList();
}
/**
* 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
* @return
*/
public List<ForecastConfiguration> getForecastConfigurations(List<String> modelIds)
{
public List<ForecastConfiguration> getForecastConfigurations(List<String> modelIds) {
return em.createNamedQuery("ForecastConfiguration.findByModelIds")
.setParameter("modelIds", modelIds)
.getResultList();
}
public List<ForecastConfiguration> getForecastConfigurations(Organization organization)
{
public List<ForecastConfiguration> getForecastConfigurations(Organization organization) {
List<VipsLogicUser> organizationUsers = em
.createNamedQuery("VipsLogicUser.findByOrganizationId")
.setParameter("organizationId", organization)
......@@ -326,16 +307,15 @@ public class ForecastBean {
.setParameter("vipsLogicUserIds", organizationUsers)
.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
.createNamedQuery("VipsLogicUser.findByOrganizationId")
.setParameter("organizationId", organization)
.getResultList();
if(!organizationUsers.isEmpty())
{
if (!organizationUsers.isEmpty()) {
return em
.createNamedQuery("ForecastConfiguration.findByVipsLogicUserIdsAndModelIdsAndDate")
.setParameter("vipsLogicUserIds", organizationUsers)
......@@ -343,22 +323,19 @@ public class ForecastBean {
.setParameter("from", from)
.setParameter("to", to)
.getResultList();
}
else
{
} else {
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
.createNamedQuery("VipsLogicUser.findByOrganizationIds")
.setParameter("organizationIds", organizationIds)
.getResultList();
if(!organizationUsers.isEmpty() && ! modelIds.isEmpty())
{
if (!organizationUsers.isEmpty() && !modelIds.isEmpty()) {
return em
.createNamedQuery("ForecastConfiguration.findByVipsLogicUserIdsAndModelIdsAndDate")
.setParameter("vipsLogicUserIds", organizationUsers)
......@@ -366,117 +343,109 @@ public class ForecastBean {
.setParameter("from", from)
.setParameter("to", to)
.getResultList();
}
else
{
} else {
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
.createNamedQuery("VipsLogicUser.findByOrganizationIds")
.setParameter("organizationIds", organizationIds)
.getResultList();
if(!organizationUsers.isEmpty())
{
if (!organizationUsers.isEmpty()) {
return em
.createNamedQuery("ForecastConfiguration.findByVipsLogicUserIdsAndDate")
.setParameter("vipsLogicUserIds", organizationUsers)
.setParameter("from", from)
.setParameter("to", to)
.getResultList();
}
else
{
} else {
return new ArrayList<>();
}
}
public List<ForecastConfiguration> getForecastConfigurationsByWeatherStation(PointOfInterestWeatherStation weatherStation)
{
public List<ForecastConfiguration> getForecastConfigurationsByWeatherStation(
PointOfInterestWeatherStation weatherStation) {
return em
.createNamedQuery("ForecastConfiguration.findByWeatherStationPointOfInterestId", ForecastConfiguration.class)
.createNamedQuery("ForecastConfiguration.findByWeatherStationPointOfInterestId",
ForecastConfiguration.class)
.setParameter("weatherStationPointOfInterestId", weatherStation)
.getResultList();
}
public List<ForecastConfiguration> getForecastConfigurationsByLocation(PointOfInterest poi)
{
public List<ForecastConfiguration> getForecastConfigurationsByLocation(PointOfInterest poi) {
return em
.createNamedQuery("ForecastConfiguration.findByLocationPointOfInterestId", ForecastConfiguration.class)
.setParameter("locationPointOfInterestId", poi)
.getResultList();
}
public List<ForecastConfiguration> getForecastConfigurations(PointOfInterestWeatherStation weatherStation,Date from, Date to)
{
public List<ForecastConfiguration> getForecastConfigurations(PointOfInterestWeatherStation weatherStation,
Date from, Date to) {
return em
.createNamedQuery("ForecastConfiguration.findByWeatherStationPointOfInterestIdAndDate", ForecastConfiguration.class)
.createNamedQuery("ForecastConfiguration.findByWeatherStationPointOfInterestIdAndDate",
ForecastConfiguration.class)
.setParameter("weatherStationPointOfInterestId", weatherStation)
.setParameter("from", from)
.setParameter("to", to)
.getResultList();
}
/**
* Deletes all forecasts and results from the given weather station
* @param weatherStation
*
* @param weatherStation
*/
public void deleteForecastConfigurationsForWeatherStation(PointOfInterestWeatherStation weatherStation)
{
List<ForecastConfiguration> forecastConfigurations = this.getForecastConfigurationsByWeatherStation(weatherStation);
for(ForecastConfiguration forecastConfiguration:forecastConfigurations)
{
public void deleteForecastConfigurationsForWeatherStation(PointOfInterestWeatherStation weatherStation) {
List<ForecastConfiguration> forecastConfigurations =
this.getForecastConfigurationsByWeatherStation(weatherStation);
for (ForecastConfiguration forecastConfiguration : forecastConfigurations) {
em.createNativeQuery("DELETE FROM forecast_result WHERE forecast_configuration_id=:forecastConfigurationId")
.setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId())
.executeUpdate();
em.remove(forecastConfiguration);
}
}
/**
* 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);
for(ForecastConfiguration forecastConfiguration:forecastConfigurations)
{
for (ForecastConfiguration forecastConfiguration : forecastConfigurations) {
em.createNativeQuery("DELETE FROM forecast_result WHERE forecast_configuration_id=:forecastConfigurationId")
.setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId())
.executeUpdate();
em.remove(forecastConfiguration);
}
}
/**
* Fetches one specific forecast configuration
*
* @param forecastConfigurationId
* @return
* @return
*/
public ForecastConfiguration getForecastConfiguration(Long forecastConfigurationId)
{
public ForecastConfiguration getForecastConfiguration(Long forecastConfigurationId) {
return em.find(ForecastConfiguration.class, forecastConfigurationId);
}
/**
* Requests all info about models currently available in VIPSCoreManager
* Stores in local db for easy access.
* Requests all info about models currently available in VIPSCoreManager Stores in local db for easy access.
*/
public TaskResult updateModelInformation()
{
public TaskResult updateModelInformation() {
TaskResult taskResult = new TaskResult();
String jobReport = "";
// Iterate all the VIPSCore instances
// Iterate all the VIPSCore instances
List<VipsCoreInstance> vipsCoreInstances = em.createNamedQuery("VipsCoreInstance.findAll").getResultList();
Integer instancesCompleted = 0;
for(VipsCoreInstance vipsCoreInstance:vipsCoreInstances) {
LOGGER.debug("Attempting to connect to " + vipsCoreInstance.getUri() );
for (VipsCoreInstance vipsCoreInstance : vipsCoreInstances) {
LOGGER.debug("Attempting to connect to " + vipsCoreInstance.getUri());
try {
Client client = ClientBuilder.newClient();
WebTarget target = client.target(vipsCoreInstance.getUri());
......@@ -486,8 +455,9 @@ public class ForecastBean {
// Get all model Ids from Core Manager
Response resp = resource.printModelListJSON();
LOGGER.debug(vipsCoreInstance.getUri() + " returned status code " + String.valueOf(resp.getStatus()));
if(resp.getStatus() != 200) {
jobReport += vipsCoreInstance.getUri() + " returned status code " + String.valueOf(resp.getStatus()) + "\n";
if (resp.getStatus() != 200) {
jobReport += vipsCoreInstance.getUri() + " returned status code " + String.valueOf(resp.getStatus())
+ "\n";
continue;
}
......@@ -509,36 +479,34 @@ public class ForecastBean {
// Retrieve and store information
Response r = resource.printModelName(modelId);
modelInformation.setDefaultName(r.readEntity(String.class));
//r.close();
// r.close();
r = resource.printModelDescription(modelId);
modelInformation.setDefaultDescription(r.readEntity(String.class));
//r.close();
// r.close();
r = resource.printModelLicense(modelId);
modelInformation.setLicense(r.readEntity(String.class));
//r.close();
// r.close();
r = resource.printModelCopyright(modelId);
modelInformation.setCopyrightHolder(r.readEntity(String.class));
//r.close();
// r.close();
r = resource.printModelUsage(modelId);
modelInformation.setUsage(r.readEntity(String.class));
//r.close();
// r.close();
r = resource.printModelSampleConfig(modelId);
modelInformation.setSampleConfig(r.readEntity(String.class));
//r.close();
// r.close();
modelInformation.setDateLastRegistered(new Date());
}
resp.close();
client.close();
instancesCompleted++;
}
catch(ProcessingException ex)
{
} catch (ProcessingException ex) {
jobReport += ex.getMessage() + "\n";
}
......@@ -547,263 +515,261 @@ public class ForecastBean {
taskResult.setMessage(jobReport);
return taskResult;
}
/**
*
* @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<>();
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);
}
return retVal;
}
/**
*
* @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<>();
this.getBatchableModels().forEach((mi) -> {
retVal.put(mi.getModelId(), mi);
});
return retVal;
}
public ModelInformation getModelInformation(String modelId)
{
try
{
return em.createNamedQuery("ModelInformation.findByModelId", ModelInformation.class).setParameter("modelId", modelId).getSingleResult();
}
catch(NoResultException ex)
{
public ModelInformation getModelInformation(String modelId) {
try {
return em.createNamedQuery("ModelInformation.findByModelId", ModelInformation.class)
.setParameter("modelId", modelId).getSingleResult();
} catch (NoResultException ex) {
return null;
}
}
/**
* Stores a forecast configuration, including model specific form fields
*
* @param forecastConfiguration
* @param formFields
* @param modelSpecificFormFields
* @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.setCropOrganismId(em.find(Organism.class, formFields.get("cropOrganismId").getValueAsInteger()));
forecastConfiguration.setPestOrganismId(em.find(Organism.class, formFields.get("pestOrganismId").getValueAsInteger()));
forecastConfiguration
.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);
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);
PointOfInterest weatherStationPoi = em.find(PointOfInterestWeatherStation.class, formFields.get("weatherStationPointOfInterestId").getValueAsInteger());
PointOfInterest weatherStationPoi = em.find(PointOfInterestWeatherStation.class,
formFields.get("weatherStationPointOfInterestId").getValueAsInteger());
forecastConfiguration.setWeatherStationPointOfInterestId(weatherStationPoi);
String timeZone = formFields.get("timeZone").getWebValue();
forecastConfiguration.setTimeZone(timeZone);
forecastConfiguration.setDateStart(formFields.get("dateStart").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 = em.merge(forecastConfiguration);
// Reset all model configurations, then store the new ones
// As for now: We keep the old ones.
// 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)
{
em.remove(configToRemove);
}
em.flush();*/
/*
* List<ForecastModelConfiguration> configsToRemove =
* em.createNamedQuery("ForecastModelConfiguration.findByForecastConfigurationId").setParameter(
* "forecastConfigurationId", forecastConfiguration.getForecastConfigurationId()).getResultList();
* for(ForecastModelConfiguration configToRemove: configsToRemove) { em.remove(configToRemove); } em.flush();
*/
// Store new values
for(FormField field : modelSpecificFormFields.values())
{
for (FormField field : modelSpecificFormFields.values()) {
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());
em.merge(forecastModelConfiguration);
}
return forecastConfiguration;
}
/**
*
* @param modelId
* @param camelCaseName
* @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());
for(String phrase : camelCaseName.split("(?=\\p{Lu})"))
{
for (String phrase : camelCaseName.split("(?=\\p{Lu})")) {
deCamelizedFieldName.append("_").append(phrase.toUpperCase());
}
return deCamelizedFieldName.toString();
}
public List<ForecastModelConfiguration> getForecastModelConfigurations(Long forecastConfigurationId)
{
return em.createNamedQuery("ForecastModelConfiguration.findByForecastConfigurationId").setParameter("forecastConfigurationId", forecastConfigurationId).getResultList();
public List<ForecastModelConfiguration> getForecastModelConfigurations(Long forecastConfigurationId) {
return em.createNamedQuery("ForecastModelConfiguration.findByForecastConfigurationId")
.setParameter("forecastConfigurationId", forecastConfigurationId).getResultList();
}
/**
* 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
// 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
// Explicit deletion of forecast_results rows is therefore necessary.
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.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.executeUpdate();
em.remove(forecastConfiguration);
}
public List<ForecastConfiguration> getForecastConfigurationsValidAtTime(Organization organization, Date time)
{
public List<ForecastConfiguration> getForecastConfigurationsValidAtTime(Organization organization, Date time) {
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) "
+ "AND :time BETWEEN date_start AND date_end "
+ "ORDER BY weather_station_point_of_interest_id ASC "
,ForecastConfiguration.class);
+ "ORDER BY weather_station_point_of_interest_id ASC ",
ForecastConfiguration.class);
q.setParameter("organizationId", organization.getOrganizationId());
q.setParameter("time", time);
return q.getResultList();
}
public void runForecast(ForecastConfiguration forecastConfiguration) throws PreprocessorException, RunModelException
{
ModelRunPreprocessor preprocessor = ModelRunPreprocessorFactory.getModelRunPreprocessor(forecastConfiguration.getModelId());
if(preprocessor != null)
{
ModelConfiguration config = preprocessor.getModelConfiguration(forecastConfiguration);
ModelRunRequest request = new ModelRunRequest(config);
Map<String,String> loginInfo = new HashMap<>();
// VIPSLogic logs in on behalf of client
ModelInformation modelInformation = em.find(ModelInformation.class, config.getModelId());
if(modelInformation.getVipsCoreInstanceId() == null)
{
throw new RunModelException("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("password",modelInformation.getVipsCoreInstanceId().getPassword());
request.setLoginInfo(loginInfo);
// We tell which client this is (the db Id in VIPSCoreManager)
Integer VIPSCoreUserId = forecastConfiguration.getVipsLogicUserId().getVipsCoreUserIdWithFallback();
if(VIPSCoreUserId == null)
{
throw new PreprocessorException("No user id found for forecast #" + forecastConfiguration.getForecastConfigurationId() +
". Possible reason: The user's organization ("
+ forecastConfiguration.getVipsLogicUserId().getOrganizationId().getOrganizationName()
+ ") hasn't got a VIPSCoreUserId.");
}
//System.out.println("VIPSCoreUserId = " + VIPSCoreUserId + ", name=" + forecastConfiguration.getVipsLogicUserId().getLastName());
request.setVipsCoreUserId(VIPSCoreUserId);
//System.out.println("RunModel for wsId " + forecastConfiguration.getWeatherStationPointOfInterestId());
//System.out.println(config.toJSON());
/* DEBUG STUFF */
/*ObjectMapper mapper = new ObjectMapper();
try
{
System.out.println(mapper.writeValueAsString(request));
}
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));
List<Result> results = (List<Result>) resp.readEntity(new GenericType<List<Result>>(){});
//System.out.println("ForecastConfigId=" + forecastConfiguration.getForecastConfigurationId() + ", resultsize=" + results.size());
// We delete all former results before we store the new ones
forecastBean.storeResults(forecastConfiguration,results);
}
else
{
throw new RunModelException(resp.readEntity(String.class));
}
//System.out.println("Finished runModel for wsId" + forecastConfiguration.getWeatherStationPointOfInterestId());
}
else
{
throw new PreprocessorException("Could not find model with id=|" + forecastConfiguration.getModelId() + "|");
public void runForecast(ForecastConfiguration forecastConfiguration)
throws PreprocessorException, RunModelException {
ModelRunPreprocessor preprocessor =
ModelRunPreprocessorFactory.getModelRunPreprocessor(forecastConfiguration.getModelId());
if (preprocessor != null) {
ModelConfiguration config = preprocessor.getModelConfiguration(forecastConfiguration);
ModelRunRequest request = new ModelRunRequest(config);
Map<String, String> loginInfo = new HashMap<>();
// VIPSLogic logs in on behalf of client
ModelInformation modelInformation = em.find(ModelInformation.class, config.getModelId());
if (modelInformation.getVipsCoreInstanceId() == null) {
throw new RunModelException(
"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("password", modelInformation.getVipsCoreInstanceId().getPassword());
request.setLoginInfo(loginInfo);
// We tell which client this is (the db Id in VIPSCoreManager)
Integer VIPSCoreUserId = forecastConfiguration.getVipsLogicUserId().getVipsCoreUserIdWithFallback();
if (VIPSCoreUserId == null) {
throw new PreprocessorException(
"No user id found for forecast #" + forecastConfiguration.getForecastConfigurationId() +
". Possible reason: The user's organization ("
+ forecastConfiguration.getVipsLogicUserId().getOrganizationId().getOrganizationName()
+ ") hasn't got a VIPSCoreUserId.");
}
// System.out.println("VIPSCoreUserId = " + VIPSCoreUserId + ", name=" +
// forecastConfiguration.getVipsLogicUserId().getLastName());
request.setVipsCoreUserId(VIPSCoreUserId);
// System.out.println("RunModel for wsId " + forecastConfiguration.getWeatherStationPointOfInterestId());
// System.out.println(config.toJSON());
/* DEBUG STUFF */
/*
* ObjectMapper mapper = new ObjectMapper(); try { System.out.println(mapper.writeValueAsString(request)); }
* 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));
List<Result> results = (List<Result>) resp.readEntity(new GenericType<List<Result>>() {});
// System.out.println("ForecastConfigId=" + forecastConfiguration.getForecastConfigurationId() + ",
// resultsize=" + results.size());
// We delete all former results before we store the new ones
forecastBean.storeResults(forecastConfiguration, results);
} else {
throw new RunModelException(resp.readEntity(String.class));
}
// System.out.println("Finished runModel for wsId" +
// forecastConfiguration.getWeatherStationPointOfInterestId());
} 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());
if(modelInformation.getVipsCoreInstanceId() == null)
{
throw new RunModelException("ERROR: Model " + modelInformation.getDefaultName() + "(" + config.getModelId() + ") is not connected to a VIPSCoreInstance. Please check your server configuration.");
if (modelInformation.getVipsCoreInstanceId() == null) {
throw new RunModelException("ERROR: Model " + modelInformation.getDefaultName() + "(" + config.getModelId()
+ ") is not connected to a VIPSCoreInstance. Please check your server configuration.");
}
ModelRunRequest request = new ModelRunRequest(config);
Map<String,String> loginInfo = new HashMap<>();
Map<String, String> loginInfo = new HashMap<>();
// VIPSLogic logs in on behalf of client
loginInfo.put("username",modelInformation.getVipsCoreInstanceId().getUsername());
//loginInfo.put("username","wrongusername");
loginInfo.put("password",modelInformation.getVipsCoreInstanceId().getPassword());
loginInfo.put("username", modelInformation.getVipsCoreInstanceId().getUsername());
// loginInfo.put("username","wrongusername");
loginInfo.put("password", modelInformation.getVipsCoreInstanceId().getPassword());
request.setLoginInfo(loginInfo);
//System.out.println("VIPSCoreUserId = " + VIPSCoreUserId + ", name=" + forecastConfiguration.getVipsLogicUserId().getLastName());
// System.out.println("VIPSCoreUserId = " + VIPSCoreUserId + ", name=" +
// forecastConfiguration.getVipsLogicUserId().getLastName());
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);
if(resp.getStatus() == Response.Status.OK.getStatusCode())
{
List<Result> results = (List<Result>) resp.readEntity(new GenericType<List<Result>>(){});
return results;
}
else
{
if (resp.getStatus() == Response.Status.OK.getStatusCode()) {
return resp.readEntity(new GenericType<>() {});
} else {
throw new RunModelException(resp.readEntity(String.class));
}
}
/**
* Get the interface for REST resources in VIPSCoreManager
* @return
*
* @return
*/
private ManagerResource getManagerResource(ModelInformation modelInformation)
{
private ManagerResource getManagerResource(ModelInformation modelInformation) {
Client client = ClientBuilder.newClient();
WebTarget target = client.target(modelInformation.getVipsCoreInstanceId().getUri());
ResteasyWebTarget rTarget = (ResteasyWebTarget) target;
ManagerResource resource = rTarget.proxy(ManagerResource.class);
return resource;
}
public Kml getForecastsAggregateKml(List<Integer> organizationIds, List<Integer> cropOrganismIds, Date theDate, String serverName, VipsLogicUser user)
{
//String iconPath = Globals.PROTOCOL + "://" + serverName + "/public/images/";
//String iconPath = "//" + serverName + "/public/images/";
public Kml getForecastsAggregateKml(List<Integer> organizationIds, List<Integer> cropOrganismIds, Date theDate,
String serverName, VipsLogicUser user) {
// String iconPath = Globals.PROTOCOL + "://" + serverName + "/public/images/";
// String iconPath = "//" + serverName + "/public/images/";
String iconPath = "https://logic.vips.nibio.no/public/images/";
// Initialization
final Vec2 hotspot = new Vec2()
......@@ -813,66 +779,60 @@ public class ForecastBean {
.withYunits(Units.FRACTION);
final Kml kml = KmlFactory.createKml();
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);
Calendar cal = Calendar.getInstance();
cal.setTime(SystemTime.getSystemTime());
for(int i=0;i<=4;i++)
{
for (int i = 0; i <= 4; i++) {
document.createAndAddStyle()
.withId("warning_type_" + i)
.withLabelStyle(noLabel)
.createAndSetIconStyle()
.withId("warning_type_" + i)
.withLabelStyle(noLabel)
.createAndSetIconStyle()
.withScale(1)
.withHotSpot(hotspot)
.createAndSetIcon()
.withHref(iconPath + "station_icon_status_" +
(cal.get(Calendar.MONTH) <= 1 ? "winter" :
cal.get(Calendar.MONTH) == Calendar.DECEMBER ? "xmas" : i)
+ ".png");
.withHref(iconPath + "station_icon_status_" +
(cal.get(Calendar.MONTH) <= 1 ? "winter"
: cal.get(Calendar.MONTH) == Calendar.DECEMBER ? "xmas" : i)
+ ".png");
}
// Run through forecast configurations
//Date benchmark = new Date();
// Run through forecast configurations
// Date benchmark = new Date();
List<PointOfInterest> poisWithAggregate = new ArrayList<>();
if(organizationIds.size() == 1 && organizationIds.get(0).equals(-1))
{
em.createNamedQuery("Organization.findAll",Organization.class).getResultStream().forEach(
org-> poisWithAggregate.addAll(getPointOfInterestForecastsAggregate(org.getOrganizationId(), cropOrganismIds, theDate, user))
);
}
else
{
if (organizationIds.size() == 1 && organizationIds.get(0).equals(-1)) {
em.createNamedQuery("Organization.findAll", Organization.class).getResultStream().forEach(
org -> poisWithAggregate.addAll(getPointOfInterestForecastsAggregate(org.getOrganizationId(),
cropOrganismIds, theDate, user)));
} else {
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();
for(PointOfInterest poiWithAggregate:poisWithAggregate)
{
for (PointOfInterest poiWithAggregate : poisWithAggregate) {
// If it's an inactive weather station, we don't produce a placemark
if(poiWithAggregate instanceof PointOfInterestWeatherStation
&& ((PointOfInterestWeatherStation) poiWithAggregate).getActive().equals(Boolean.FALSE)
)
{
if (poiWithAggregate instanceof PointOfInterestWeatherStation
&& ((PointOfInterestWeatherStation) poiWithAggregate).getActive().equals(Boolean.FALSE)) {
continue;
}
// Adding infoUri (direct link to weather station information) as extra attribute
String infoUriValue = "";
if(poiWithAggregate instanceof PointOfInterestWeatherStation)
{
String infoUriExpression = ((PointOfInterestWeatherStation) poiWithAggregate).getWeatherStationDataSourceId().getInfoUriExpression();
if(!infoUriExpression.isEmpty())
{
infoUriValue = String.format(infoUriExpression, ((PointOfInterestWeatherStation) poiWithAggregate).getWeatherStationRemoteId());
if (poiWithAggregate instanceof PointOfInterestWeatherStation) {
String infoUriExpression = ((PointOfInterestWeatherStation) poiWithAggregate)
.getWeatherStationDataSourceId().getInfoUriExpression();
if (!infoUriExpression.isEmpty()) {
infoUriValue = String.format(infoUriExpression,
((PointOfInterestWeatherStation) poiWithAggregate).getWeatherStationRemoteId());
}
}
Data infoUri = new Data(infoUriValue);
......@@ -884,43 +844,44 @@ public class ForecastBean {
dataList.add(stationName);
ExtendedData extendedData = document.createAndSetExtendedData()
.withData(dataList);
final Placemark placemark = document.createAndAddPlacemark()
//.withName(poiWithAggregate.getName())
.withDescription("<![CDATA[Mangler informasjon om varsler for " + poiWithAggregate.getName() + "]]>")
.withStyleUrl("#warning_type_"
+ (poiWithAggregate.getProperties().get("forecastsAggregate") != null ? poiWithAggregate.getProperties().get("forecastsAggregate") : "0")
)
.withId(poiWithAggregate.getPointOfInterestId().toString())
.withExtendedData(extendedData);
// .withName(poiWithAggregate.getName())
.withDescription(
"<![CDATA[Mangler informasjon om varsler for " + poiWithAggregate.getName() + "]]>")
.withStyleUrl("#warning_type_"
+ (poiWithAggregate.getProperties().get("forecastsAggregate") != null
? poiWithAggregate.getProperties().get("forecastsAggregate")
: "0"))
.withId(poiWithAggregate.getPointOfInterestId().toString())
.withExtendedData(extendedData);
final Point point = placemark.createAndSetPoint();
List<Coordinate> coord = point.createAndSetCoordinates();
coord.add(gisUtil.getKMLCoordinateFromJTSCoordinate(poiWithAggregate.getGisGeom().getCoordinate()));
}
//System.out.println(kml.marshal());
// System.out.println(kml.marshal());
return kml;
}
/**
* The table forecast_result_cache always should contain the forecast
* results from TODAY (The system's time, which is configurable)
* The table forecast_result_cache always should contain the forecast results from TODAY (The system's time, which
* is configurable)
*/
public void updateForecastResultCacheTable()
{
// Because we might be in completely different time zones,
public void updateForecastResultCacheTable() {
// 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
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
cal.setTime(SystemTime.getSystemTime());
cal.set(Calendar.HOUR_OF_DAY, 12);
cal.set(Calendar.MINUTE,0);
cal.set(Calendar.SECOND,0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.add(Calendar.DATE, -1);
Date startTime = cal.getTime();
cal.add(Calendar.DATE,2);
cal.add(Calendar.DATE, 2);
Date endTime = cal.getTime();
String transactionSQL = new StringBuilder()
.append("BEGIN;")
......@@ -936,55 +897,53 @@ public class ForecastBean {
.append(" );")
.append("END;")
.toString();
Query query = em.createNativeQuery(transactionSQL);
query.setParameter("startTime", startTime);
query.setParameter("endTime", endTime);
query.setParameter("currentDate", SystemTime.getSystemTime());
query.executeUpdate();
}
/**
* The table forecast_summary should contain forecast summaries
* from +/- 10 days related to TODAY (The system's time, which is configurable)
* The table forecast_summary should contain forecast summaries from +/- 10 days related to TODAY (The system's
* time, which is configurable)
*/
public void updateForecastSummaryTable(Date currentDate)
{
//
public void updateForecastSummaryTable(Date currentDate) {
//
// Collect all forecasts that are active TODAY
// This
// This
List<ForecastConfiguration> activeForecasts = em.createNamedQuery("ForecastConfiguration.findAllActiveAtDate")
.setParameter("currentDate", currentDate).getResultList();
// Loop through them
List<Long> activeForecastIds = new ArrayList<>();
Query deleteQ = em.createNativeQuery(
"DELETE FROM forecast_summary "
+ "WHERE forecast_configuration_id = :forecastConfigurationId");
"DELETE FROM forecast_summary "
+ "WHERE forecast_configuration_id = :forecastConfigurationId");
Query findQ = em.createNamedQuery("ForecastResult.findByForecastConfigurationIdAndPeriod");
for(ForecastConfiguration forecastConfiguration:activeForecasts)
{
for (ForecastConfiguration forecastConfiguration : activeForecasts) {
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,
// to prevent loss of data in case of software error)
deleteQ.setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId())
.executeUpdate();
// Get all results that are within +/- 10 days from TODAY (taking
.executeUpdate();
// Get all results that are within +/- 10 days from TODAY (taking
// time zone into account)
TimeZone forecastTimeZone = forecastConfiguration.getTimeZone() != null ?
TimeZone.getTimeZone(forecastConfiguration.getTimeZone())
: TimeZone.getTimeZone(forecastConfiguration.getVipsLogicUserId().getOrganizationId().getDefaultTimeZone())
;
TimeZone forecastTimeZone = forecastConfiguration.getTimeZone() != null
? TimeZone.getTimeZone(forecastConfiguration.getTimeZone())
: TimeZone.getTimeZone(
forecastConfiguration.getVipsLogicUserId().getOrganizationId().getDefaultTimeZone());
Calendar cal = Calendar.getInstance(forecastTimeZone);
cal.setTime(currentDate);
cal.add(Calendar.DATE, -10);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE,0);
cal.set(Calendar.SECOND,0);
cal.set(Calendar.MILLISECOND,0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
Date tenDaysAgo = cal.getTime();
cal.add(Calendar.DATE, 20);
Date tenDaysAhead = cal.getTime();
......@@ -993,174 +952,166 @@ public class ForecastBean {
.setParameter("timeEnd", tenDaysAhead)
.setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId())
.getResultList();
// Loop through each day (take timezone into account!), find worst warning
Collections.sort(results);
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
format.setTimeZone(forecastTimeZone);
Map<String, Integer> resultDailyAggregate = new HashMap<>();
for(ForecastResult result:results)
{
for (ForecastResult result : results) {
String dayStamp = format.format(result.getValidTimeStart());
Integer currentWorstCode = resultDailyAggregate.get(dayStamp);
resultDailyAggregate.put(dayStamp,
Math.max(
currentWorstCode != null ? currentWorstCode : 0,
result.getWarningStatus()
)
);
resultDailyAggregate.put(dayStamp,
Math.max(
currentWorstCode != null ? currentWorstCode : 0,
result.getWarningStatus()));
}
for(String dayStamp: resultDailyAggregate.keySet())
{
for (String dayStamp : resultDailyAggregate.keySet()) {
Date aggregateDay;
try {
// 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(
forecastConfiguration.getForecastConfigurationId(),
aggregateDay
);
forecastConfiguration.getForecastConfigurationId(),
aggregateDay);
ForecastSummary summary = new ForecastSummary(summaryPK);
summary.setSummaryCreatedTime(new Date());
summary.setWarningStatus(resultDailyAggregate.get(dayStamp));
em.persist(summary);
} catch (ParseException 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
em.createNativeQuery("DELETE FROM forecast_summary "
+ "WHERE forecast_configuration_id NOT IN :activeForecastIds")
.setParameter("activeForecastIds", activeForecastIds)
.executeUpdate();
}
else
{
} else {
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")
.setParameter("forecastConfigurationIds", forecastConfigurationIds)
.getResultList();
for(ForecastConfiguration config: retVal)
{
for (ForecastConfiguration config : retVal) {
Query q = em.createNamedQuery("ForecastSummary.findByForecastConfigurationId");
config.setForecastSummaries(
q.setParameter("forecastConfigurationId", config.getForecastConfigurationId())
.getResultList()
);
.getResultList());
}
return retVal;
}
/**
* Finds the forecast configuration summaries for a given organization and that this user has access to
*
* @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")
.setParameter("organizationId", em.find(Organization.class, organizationId))
.getResultList();
Map<Long, List<ForecastSummary>> mappedSummaries = new HashMap<>();
summaries.forEach((s) -> {
List<ForecastSummary> summaryForForecast = mappedSummaries.get(s.getForecastSummaryPK().getForecastConfigurationId()) != null ?
mappedSummaries.get(s.getForecastSummaryPK().getForecastConfigurationId()) :
new ArrayList<>();
List<ForecastSummary> summaryForForecast =
mappedSummaries.get(s.getForecastSummaryPK().getForecastConfigurationId()) != null
? mappedSummaries.get(s.getForecastSummaryPK().getForecastConfigurationId())
: new ArrayList<>();
summaryForForecast.add(s);
mappedSummaries.put(s.getForecastSummaryPK().getForecastConfigurationId(), summaryForForecast);
});
if(mappedSummaries.size() > 0)
{
List<ForecastConfiguration> configurations = em.createNamedQuery("ForecastConfiguration.findByForecastConfigurationIds").setParameter("forecastConfigurationIds", mappedSummaries.keySet()).getResultList();
if (mappedSummaries.size() > 0) {
List<ForecastConfiguration> configurations =
em.createNamedQuery("ForecastConfiguration.findByForecastConfigurationIds")
.setParameter("forecastConfigurationIds", mappedSummaries.keySet()).getResultList();
// 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) -> {
conf.setForecastSummaries(mappedSummaries.get(conf.getForecastConfigurationId()));
});
return configurations;
}
else
{
} else {
return new ArrayList<>();
}
}
/**
* Selects the "worst" (highest infection risk) warning status for forecasts
* running at the pois connected to the given organization
* Selects the "worst" (highest infection risk) warning status for forecasts running at the pois connected to the
* given organization
*
* @param organizationId Filter for organization
* @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
* @return
* @return
*/
private List<PointOfInterest> getPointOfInterestForecastsAggregate(
Integer organizationId,
List<Integer> cropOrganismIds,
Integer organizationId,
List<Integer> cropOrganismIds,
Date theDate,
VipsLogicUser user
) {
VipsLogicUser user) {
// TODO: More precise gathering of POIs...
List<PointOfInterest> pois;
if(organizationId != null && organizationId > 0)
{
if (organizationId != null && organizationId > 0) {
pois = em.createNamedQuery("PointOfInterest.findForecastLocationsByOrganizationId")
.setParameter("organizationId", em.find(Organization.class, organizationId))
.getResultList();
}
else
{
.setParameter("organizationId", em.find(Organization.class, organizationId))
.getResultList();
} else {
pois = em.createNamedQuery("PointOfInterest.findAll").getResultList();
}
String dateFormat = "yyyy-MM-dd";
SimpleDateFormat format = new SimpleDateFormat(dateFormat);
// 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";
//this.updateForecastResultCacheTable();
String tableName =
(format.format(theDate).equals(format.format(SystemTime.getSystemTime()))) ? "forecast_result_cache"
: "forecast_result";
// this.updateForecastResultCacheTable();
Calendar cal = Calendar.getInstance();
cal.setTime(theDate);
WeatherUtil wUtil = new WeatherUtil();
for(PointOfInterest poi: pois)
{
for (PointOfInterest poi : pois) {
Date midnight = wUtil.normalizeToExactDate(theDate, TimeZone.getTimeZone(poi.getTimeZone()));
cal.setTime(theDate);
cal.add(Calendar.DATE, 1);
Date nextMidnight = cal.getTime();
String sql = "SELECT max(warning_status) FROM " + tableName + " \n" +
"WHERE forecast_configuration_id IN( \n" +
" SELECT forecast_configuration_id \n" +
" FROM forecast_configuration \n" +
" WHERE forecast_configuration_id > 0 \n" +
(user == null ?
" AND is_private IS FALSE \n"
:" AND (is_private IS FALSE OR (is_private IS TRUE AND vips_logic_user_id=:vipsLogicUserId))"
) +
" AND location_point_of_interest_id=:locationPointOfInterestId \n" +
(cropOrganismIds != null && ! cropOrganismIds.isEmpty() ? " AND crop_organism_id IN (" + StringUtils.join(cropOrganismIds, ",") + ") " : "") +
")\n" +
"AND valid_time_start between :midnight AND :nextMidnight";
//System.out.println(poi.getName() + " SQL=" + sql);
"WHERE forecast_configuration_id IN( \n" +
" SELECT forecast_configuration_id \n" +
" FROM forecast_configuration \n" +
" WHERE forecast_configuration_id > 0 \n" +
(user == null ? " AND is_private IS FALSE \n"
: " AND (is_private IS FALSE OR (is_private IS TRUE AND vips_logic_user_id=:vipsLogicUserId))")
+
" AND location_point_of_interest_id=:locationPointOfInterestId \n" +
(cropOrganismIds != null && !cropOrganismIds.isEmpty()
? " AND crop_organism_id IN (" + StringUtils.join(cropOrganismIds, ",") + ") "
: "")
+
")\n" +
"AND valid_time_start between :midnight AND :nextMidnight";
// System.out.println(poi.getName() + " SQL=" + sql);
Query q = em.createNativeQuery(sql);
if(user != null)
{
if (user != null) {
q.setParameter("vipsLogicUserId", user);
}
q.setParameter("locationPointOfInterestId", poi.getPointOfInterestId());
......@@ -1168,152 +1119,148 @@ public class ForecastBean {
q.setParameter("nextMidnight", nextMidnight);
Integer result = (Integer) q.getSingleResult();
poi.getProperties().put("forecastsAggregate", result);
}
return pois;
}
/**
* Returns the latest forecast results for given point of interest
*
* @param poiId
* @return
* @return
*/
public Map<String, Object> getLatestForecastResultsForPoi(Integer poiId) {
Map<String, Object> retVal = new HashMap<>();
PointOfInterest poi = em.find(PointOfInterest.class, poiId);
List<ForecastConfiguration> forecastConfigurations =
em.createNamedQuery("ForecastConfiguration.findByLocationPointOfInterestId")
.setParameter("locationPointOfInterestId", poi)
.getResultList();
HashMap<Long,ForecastConfiguration> mappedForecastConfigurations = new HashMap<>();
List<ForecastConfiguration> forecastConfigurations =
em.createNamedQuery("ForecastConfiguration.findByLocationPointOfInterestId")
.setParameter("locationPointOfInterestId", poi)
.getResultList();
HashMap<Long, ForecastConfiguration> mappedForecastConfigurations = new HashMap<>();
List<ForecastResult> results = new ArrayList<>();
for(ForecastConfiguration forecastConfiguration:forecastConfigurations)
{
if(forecastConfiguration.getIsPrivate())
{
for (ForecastConfiguration forecastConfiguration : forecastConfigurations) {
if (forecastConfiguration.getIsPrivate()) {
continue;
}
mappedForecastConfigurations.put(forecastConfiguration.getForecastConfigurationId(), forecastConfiguration);
Query q = em.createNativeQuery(
"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)",
ForecastResult.class
);
+ "AND valid_time_start = (SELECT max(valid_time_start) FROM forecast_result WHERE forecast_configuration_id = :forecastConfigurationId)",
ForecastResult.class);
q.setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId());
try
{
results.add((ForecastResult)q.getSingleResult());
}
catch(NoResultException ex)
{
try {
results.add((ForecastResult) q.getSingleResult());
} catch (NoResultException ex) {
// 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
}
}
retVal.put("forecastConfigurations", mappedForecastConfigurations);
retVal.put("results", results);
retVal.put("pointOfInterest", poi);
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.setModelId(formFields.get("modelId").getWebValue());
forecastConfiguration.setCropOrganismId(em.find(Organism.class, formFields.get("cropOrganismId").getValueAsInteger()));
forecastConfiguration.setPestOrganismId(em.find(Organism.class, formFields.get("pestOrganismId").getValueAsInteger()));
forecastConfiguration
.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);
// In the multiple form, location and weatherstation is the same
PointOfInterest locationPoi = em.find(PointOfInterest.class, weatherStationPointOfInterestId);
forecastConfiguration.setLocationPointOfInterestId(locationPoi);
PointOfInterest weatherStationPoi = em.find(PointOfInterestWeatherStation.class, weatherStationPointOfInterestId);
PointOfInterest weatherStationPoi =
em.find(PointOfInterestWeatherStation.class, weatherStationPointOfInterestId);
forecastConfiguration.setWeatherStationPointOfInterestId(weatherStationPoi);
String timeZone = formFields.get("timeZone").getWebValue();
forecastConfiguration.setTimeZone(timeZone);
forecastConfiguration.setDateStart(formFields.get("dateStart").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 = em.merge(forecastConfiguration);
// Store new values
for(FormField field : modelSpecificFormFields.values())
{
for (FormField field : modelSpecificFormFields.values()) {
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());
em.merge(forecastModelConfiguration);
}
return forecastConfiguration;
}
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)
List<ForecastConfiguration> filteredConfigs = new ArrayList<>();
Query q = em.createNamedQuery("ForecastSummary.findByForecastConfigurationId");
for(ForecastConfiguration config: forecastConfigurations)
{
for (ForecastConfiguration config : forecastConfigurations) {
config.setForecastSummaries(
q.setParameter("forecastConfigurationId", config.getForecastConfigurationId())
.getResultList()
);
if(config.getForecastSummaries() != null && !config.getForecastSummaries().isEmpty())
{
.getResultList());
if (config.getForecastSummaries() != null && !config.getForecastSummaries().isEmpty()) {
filteredConfigs.add(config);
}
}
return filteredConfigs;
}
/**
*
* @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();
return modelInfos.stream()
.filter(modelInfo -> ModelRunPreprocessorFactory.getModelRunPreprocessor(modelInfo.getModelId()) != null)
.filter(modelInfo -> ModelRunPreprocessorFactory
.getModelRunPreprocessor(modelInfo.getModelId()) != null)
.collect(Collectors.toList());
}
public void deleteAllPrivateForecastConfigurationsForUser(VipsLogicUser user) {
em.createNativeQuery(
"DELETE FROM public.forecast_result WHERE forecast_configuration_id IN "
+ "("
+ " SELECT forecast_configuration_id "
+ " FROM public.forecast_configuration "
+ " WHERE is_private IS TRUE "
+ " AND vips_logic_user_id = :userId "
+ ")"
)
.setParameter("userId", user.getUserId())
.executeUpdate();
+ "("
+ " SELECT forecast_configuration_id "
+ " FROM public.forecast_configuration "
+ " WHERE is_private IS TRUE "
+ " AND vips_logic_user_id = :userId "
+ ")")
.setParameter("userId", user.getUserId())
.executeUpdate();
em.createNativeQuery(
"DELETE FROM public.forecast_configuration "
+ " WHERE is_private IS TRUE "
+ " AND vips_logic_user_id = :userId"
)
.setParameter("userId", user.getUserId())
.executeUpdate();
+ " WHERE is_private IS TRUE "
+ " AND vips_logic_user_id = :userId")
.setParameter("userId", user.getUserId())
.executeUpdate();
}
/**
*
* @param modelId
* @param year
* @return
* @return
*/
public List<ForecastConfiguration> getForecastConfigurationsForModel(String modelId, Integer year) {
return em.createNamedQuery("ForecastConfiguration.findByModelIdAndYear")
......
......@@ -26,11 +26,11 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import jakarta.ejb.Stateless;
import jakarta.persistence.EntityManager;
import jakarta.persistence.NoResultException;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;
import no.nibio.vips.logic.entity.Message;
import no.nibio.vips.logic.entity.MessageIllustration;
import no.nibio.vips.logic.entity.MessageIllustrationCaptionLocale;
......@@ -43,7 +43,7 @@ import no.nibio.vips.logic.entity.Organization;
import no.nibio.vips.logic.entity.VipsLogicUser;
import no.nibio.vips.logic.util.SystemTime;
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;
/**
......@@ -186,7 +186,7 @@ public class MessageBean {
cropCategoryIds.add(Integer.valueOf(cropCategoryId));
}
}
message.setCropCategoryIds(cropCategoryIds.toArray(new Integer[cropCategoryIds.size()]));
message.setCropCategoryIds(cropCategoryIds);
return message;
}
......@@ -224,7 +224,7 @@ public class MessageBean {
}
// Store file
item.write(illustration);
item.write(illustration.toPath());
// Update MessageIllustrations
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
* it under the terms of the GNU Affero General Public License as published by
......@@ -18,19 +18,13 @@
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.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
......@@ -39,16 +33,30 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.function.Function;
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.servlet.http.HttpServletRequest;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.fileupload2.core.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;
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.Gis;
import no.nibio.vips.logic.entity.Observation;
......@@ -56,6 +64,7 @@ import no.nibio.vips.logic.entity.ObservationFormShortcut;
import no.nibio.vips.logic.entity.ObservationIllustration;
import no.nibio.vips.logic.entity.ObservationIllustrationPK;
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.Organization;
import no.nibio.vips.logic.entity.PointOfInterest;
......@@ -63,190 +72,168 @@ import no.nibio.vips.logic.entity.PolygonService;
import no.nibio.vips.logic.entity.VipsLogicUser;
import no.nibio.vips.logic.i18n.SessionLocaleUtil;
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.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>
* @copyright 2014-2020 <a href="http://www.nibio.no/">NIBIO</a>
*/
@Stateless
public class ObservationBean {
@PersistenceContext(unitName="VIPSLogic-PU")
private static final Logger LOGGER = LoggerFactory.getLogger(ObservationBean.class);
@PersistenceContext(unitName = "VIPSLogic-PU")
EntityManager em;
@EJB
PointOfInterestBean pointOfInterestBean;
@EJB
UserBean userBean;
private static Logger LOGGER = LoggerFactory.getLogger(ObservationBean.class);
public List<Observation> getObservations(Integer organizationId)
{
Organization organization = em.find(Organization.class,organizationId);
@EJB
ObservationTimeSeriesBean observationTimeSeriesBean;
public List<Observation> getObservations(Integer organizationId) {
Organization organization = em.find(Organization.class, organizationId);
List<Observation> observations = em.createNamedQuery("Observation.findByOrganizationId")
.setParameter("organizationId", organization)
.getResultList();
observations = this.getObservationsWithGeoInfo(observations);
observations = this.getObservationsWithLocations(observations);
observations = this.getObservationsWithObservers(observations);
return observations;
return observations;
}
public List<Observation> getObservations(Integer organizationId, Date periodStart, Date periodEnd)
{
Organization organization = em.find(Organization.class,organizationId);
public List<Observation> getObservations(Integer organizationId, Date periodStart, Date periodEnd) {
Organization organization = em.find(Organization.class, organizationId);
List<Observation> observations = em.createNamedQuery("Observation.findByOrganizationIdAndPeriod")
.setParameter("organizationId", organization)
.setParameter("start", periodStart)
.setParameter("end", periodEnd)
.getResultList();
observations = this.getObservationsWithGeoInfo(observations);
observations = this.getObservationsWithLocations(observations);
observations = this.getObservationsWithObservers(observations);
return observations;
}
public List<Observation> getObservations(Integer organizationId, Integer statusTypeId)
{
Organization organization= em.find(Organization.class, organizationId);
public List<Observation> getObservations(Integer organizationId, Integer statusTypeId) {
Organization organization = em.find(Organization.class, organizationId);
/*List<VipsLogicUser> users = em.createNamedQuery("VipsLogicUser.findByOrganizationId", VipsLogicUser.class)
.setParameter("organizationId", organization)
.getResultList();*/
List<Observation> retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByOrganizationIdAndStatusTypeId")
.setParameter("organizationId", organization)
.setParameter("statusTypeId", statusTypeId)
.getResultList());
return retVal;
}
public List<Observation> getObservationsForUser(VipsLogicUser user)
{
public List<Observation> getObservationsForUser(VipsLogicUser user) {
List<Observation> retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByUserId")
.setParameter("userId", user.getUserId())
.getResultList());
retVal = this.getObservationsWithLocations(retVal);
retVal = this.getObservationsWithObservers(retVal);
return retVal;
}
public List<Observation> getObservationsLastEditedByUser(VipsLogicUser user) {
List<Observation> retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByLastEditedBy")
.setParameter("lastEditedBy", user.getUserId())
.getResultList());
retVal = this.getObservationsWithLocations(retVal);
retVal = this.getObservationsWithObservers(retVal);
return retVal;
}
public List<Observation> getObservationsStatusChangedByUser(VipsLogicUser user) {
List<Observation> retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByStatusChangedByUserId")
.setParameter("statusChangedByUserId", user.getUserId())
.getResultList());
retVal = this.getObservationsWithLocations(retVal);
retVal = this.getObservationsWithObservers(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")
.setParameter("userId", user.getUserId())
.setParameter("start", periodStart)
.setParameter("end", periodEnd)
.getResultList());
retVal = this.getObservationsWithLocations(retVal);
retVal = this.getObservationsWithObservers(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")
.setParameter("userId", user.getUserId())
.setParameter("statusTypeId", statusTypeId)
.getResultList());
return retVal;
}
public Observation getObservation(Integer observationId)
{
public Observation getObservation(Integer observationId) {
Observation retVal = em.find(Observation.class, observationId);
if(retVal != null)
{
if (retVal != null) {
retVal.setGeoinfos(this.getGeoinfoForObservation(retVal));
retVal.setUser(em.find(VipsLogicUser.class, retVal.getUserId()));
if(retVal.getLastEditedBy() != null)
{
if (retVal.getLastEditedBy() != null) {
retVal.setLastEditedByUser(em.find(VipsLogicUser.class, retVal.getLastEditedBy()));
}
}
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")
.setParameter("observationId", obs.getObservationId())
.getResultList();
if(gisIds != null && ! gisIds.isEmpty())
{
return em.createNamedQuery("Gis.findByGisIds",Gis.class)
if (gisIds != null && !gisIds.isEmpty()) {
return em.createNamedQuery("Gis.findByGisIds", Gis.class)
.setParameter("gisIds", gisIds)
.getResultList();
}
else
{
} else {
return null;
}
}
public List<Observation> getObservationsWithGeoInfo(List<Observation> observations)
{
if(observations.isEmpty())
{
public List<Observation> getObservationsWithGeoInfo(List<Observation> observations) {
if (observations.isEmpty()) {
return observations;
}
// 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....
// Indexing observations
Map<Integer, Observation> obsBucket = new HashMap<>();
observations.stream().forEach((obs) -> {
obsBucket.put(obs.getObservationId(), obs);
});
// Getting many-to-many relations
Query q = em.createNativeQuery("SELECT gis_id, observation_id FROM public.gis_observation WHERE observation_id IN :observationIds");
q.setParameter("observationIds", obsBucket.keySet());
List<Object[]> gisObservationIds = q.getResultList();
// 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);
List<Gis> geoInfos = q2.setParameter("observationIds", obsBucket.keySet()).getResultList();
......@@ -254,7 +241,7 @@ public class ObservationBean {
geoInfos.stream().forEach((geoinfo) -> {
gisBucket.put(geoinfo.getGisId(), geoinfo);
});
// Iterating the many-to-many relations,
// adding geoinfo to the correct observations
gisObservationIds.stream().forEach((gisObsIds) -> {
......@@ -262,12 +249,11 @@ public class ObservationBean {
Integer observationId = (Integer) gisObsIds[1];
obsBucket.get(observationId).addGeoInfo(gisBucket.get(gisId));
});
return observations;
}
/**
*
* @param observation
* @return The merged object
*/
......@@ -283,14 +269,13 @@ public class ObservationBean {
.setParameter("observationId", retVal.getObservationId())
.executeUpdate();
// Then persist the new ones
if(observation.getGeoinfos() != null && ! observation.getGeoinfos().isEmpty())
{
if (observation.getGeoinfos() != null && !observation.getGeoinfos().isEmpty()) {
observation.getGeoinfos().stream().forEach((gis) -> {
em.persist(gis);
});
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) -> {
q.setParameter("gisId", gis.getGisId())
.executeUpdate();
......@@ -304,54 +289,49 @@ public class ObservationBean {
em.persist(gis);
gises.add(gis);
}*/
// The GisObservations are not included in the merged object, so we should add them
retVal.setGeoinfos(this.getGeoinfoForObservation(retVal));
return retVal;
}
public void deleteObservation(Integer observationId) {
Observation observation = em.find(Observation.class, observationId);
if(observation != null)
{
// Delete all current group memberships
if (observation != null) {
// Delete all current group memberships
em.createNativeQuery("DELETE FROM public.organization_group_observation WHERE observation_id=:observationId")
.setParameter("observationId", observation.getObservationId())
.executeUpdate();
// Delete all illustrations (including removing files on disk)
String[] filesToDelete = observation.getObservationIllustrationSet().stream()
.map(ill->ill.getObservationIllustrationPK().getFileName())
.collect(Collectors.toList())
.toArray(new String[0]);
.map(ill -> ill.getObservationIllustrationPK().getFileName())
.collect(Collectors.toList())
.toArray(new String[0]);
this.deleteObservationIllustration(observation, filesToDelete);
em.remove(observation);
}
}
/**
*
* @param organizationId
* @param season
* @return
* @return
*/
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)
.setParameter("organizationId", organization)
.getResultList();*/
List<Observation> retVal = null;
if(season == null)
{
retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByOrganizationIdAndStatusTypeIdAndBroadcastMessage")
if (season == null) {
retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByOrganizationIdAndStatusTypeIdAndBroadcastMessage")
.setParameter("organizationId", organization)
.setParameter("statusTypeId", Observation.STATUS_TYPE_ID_APPROVED)
.getResultList());
}
else
{
} else {
Calendar cal = Calendar.getInstance();
cal.set(season, Calendar.JANUARY, 1, 0, 0, 0);
Date start = cal.getTime();
......@@ -361,31 +341,29 @@ public class ObservationBean {
}
return retVal;
}
/**
*
* @param organizationId
* @param start When period starts. Default: Jan 1st 2000
* @param end When period ends. Default: 100 years from now
* @return
* @param start When period starts. Default: Jan 1st 2000
* @param end When period ends. Default: 100 years from now
* @return
*/
public List<Observation> getBroadcastObservations(Integer organizationId, Date start, Date end) {
if(start == null || end == null)
{
if (start == null || end == null) {
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();
}
if(end == null) // Default: Today + 100 years
if (end == null) // Default: Today + 100 years
{
cal.setTime(SystemTime.getSystemTime());
cal.add(Calendar.YEAR, 100);
end = cal.getTime();
}
}
Organization organization= em.find(Organization.class, organizationId);
Organization organization = em.find(Organization.class, organizationId);
return this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByOrganizationIdAndStatusTypeIdAndBroadcastMessageAndPeriod")
.setParameter("organizationId", organization)
.setParameter("statusTypeId", Observation.STATUS_TYPE_ID_APPROVED)
......@@ -393,45 +371,42 @@ public class ObservationBean {
.setParameter("end", end)
.getResultList());
}
/**
*
* @param observation
* @return [OBSERVATION_ILLUSTRATION_PATH]/[ORGANISM_ID]/
*/
private String getFilePath(Observation observation)
{
return System.getProperty("no.nibio.vips.logic.OBSERVATION_ILLUSTRATION_PATH") + "/"
+ observation.getOrganismId();
}
public Observation storeObservationIllustration(Observation observation, String fileName, String base64Data)
{
String[] metaAndData = base64Data.split(",");
byte[] imageData = Base64.decodeBase64(metaAndData[1]);
Path path = Paths.get(this.getFilePath(observation) + "/" + fileName);
try {
// Make sure the directory exists
File testDirectoryfile = new File(this.getFilePath(observation));
if(!testDirectoryfile.exists())
{
testDirectoryfile.mkdirs();
}
Files.write(path,imageData, StandardOpenOption.CREATE);
ObservationIllustration newIllustration = new ObservationIllustration(new ObservationIllustrationPK(observation.getObservationId(), fileName));
newIllustration = em.merge(newIllustration);
// Add the new illustration
if(observation.getObservationIllustrationSet() == null)
{
observation.setObservationIllustrationSet(new HashSet<ObservationIllustration>());
}
observation.getObservationIllustrationSet().add(newIllustration);
return observation;
}
catch(IOException ex) {ex.printStackTrace(); return observation;}
private String getFilePath(Observation observation) {
return System.getProperty("no.nibio.vips.logic.OBSERVATION_ILLUSTRATION_PATH") + "/"
+ observation.getOrganismId();
}
public Observation storeObservationIllustration(Observation observation, String fileName, String base64Data) {
String[] metaAndData = base64Data.split(",");
byte[] imageData = Base64.decodeBase64(metaAndData[1]);
Path path = Paths.get(this.getFilePath(observation) + "/" + fileName);
try {
// Make sure the directory exists
File testDirectoryfile = new File(this.getFilePath(observation));
if (!testDirectoryfile.exists()) {
testDirectoryfile.mkdirs();
}
Files.write(path, imageData, StandardOpenOption.CREATE);
ObservationIllustration newIllustration = new ObservationIllustration(new ObservationIllustrationPK(observation.getObservationId(), fileName));
newIllustration = em.merge(newIllustration);
// Add the new illustration
if (observation.getObservationIllustrationSet() == null) {
observation.setObservationIllustrationSet(new HashSet<ObservationIllustration>());
}
observation.getObservationIllustrationSet().add(newIllustration);
return observation;
} catch (IOException ex) {
ex.printStackTrace();
return observation;
}
}
public Observation storeObservationIllustration(Observation observation, FileItem item) throws Exception {
......@@ -442,32 +417,29 @@ public class ObservationBean {
// Check availability, and adapt filename until available
Integer fileNameSuffix = 1;
File illustration = new File(filePath + "/" + fileName);
while(illustration.exists())
{
while (illustration.exists()) {
fileName = observation.getObservationId() + "_illustration_" + fileNameSuffix + "." + FilenameUtils.getExtension(item.getName());
illustration = new File(filePath + "/" + fileName);
fileNameSuffix++;
}
File testDirectoryfile = new File(filePath);
// If directory does not exist, create it
if(!testDirectoryfile.exists())
{
if (!testDirectoryfile.exists()) {
testDirectoryfile.mkdirs();
}
// Store file
item.write(illustration);
item.write(illustration.toPath());
// Update MessageIllustrations
observation = em.merge(observation);
// Remove the old illustration(s)
ObservationIllustration newIllustration = new ObservationIllustration(new ObservationIllustrationPK(observation.getObservationId(), fileName));
em.persist(newIllustration);
// Add the new illustration
if(observation.getObservationIllustrationSet() == null)
{
if (observation.getObservationIllustrationSet() == null) {
observation.setObservationIllustrationSet(new HashSet<ObservationIllustration>());
}
observation.getObservationIllustrationSet().add(newIllustration);
......@@ -476,127 +448,139 @@ public class ObservationBean {
public Observation deleteObservationIllustration(Observation observation, String[] deleteIllustrations) {
observation = em.merge(observation);
Set <ObservationIllustration> formerIllustrations = observation.getObservationIllustrationSet();
if(formerIllustrations == null)
{
return observation;
Set<ObservationIllustration> formerIllustrations = observation.getObservationIllustrationSet();
if (formerIllustrations == null) {
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;
}
/**
* Fetch observations of a particular organism at a particular place and period
*
* @param organismId
* @param pointOfInterestId
* @param startDate
* @param endDate
* @return
* @return
*/
public List<no.nibio.vips.observation.Observation> getObservations(Integer organismId, Integer pointOfInterestId, Date startDate, Date endDate) {
/*System.out.println("organismId = " + organismId);
System.out.println("pointOfInterestId = " + pointOfInterestId);
System.out.println("period= " + startDate + "-" + endDate);*/
return em.createNativeQuery(
"SELECT * FROM public.observation "
+ "WHERE organism_id = :organismId "
+ "AND location_point_of_interest_id = :locationPointOfInterestId "
+ "AND time_of_observation BETWEEN :startDate AND :endDate"
,Observation.class
)
"SELECT * FROM public.observation "
+ "WHERE organism_id = :organismId "
+ "AND location_point_of_interest_id = :locationPointOfInterestId "
+ "AND time_of_observation BETWEEN :startDate AND :endDate"
, Observation.class
)
.setParameter("organismId", organismId)
.setParameter("locationPointOfInterestId",pointOfInterestId)
.setParameter("locationPointOfInterestId", pointOfInterestId)
.setParameter("startDate", startDate)
.setParameter("endDate", endDate)
.getResultList();
}
public List<Observation> getObservationsWithLocations(List<Observation> observations) {
Set<Integer> locationPointOfInterestIds = new HashSet<>();
observations.stream().filter((o) -> (o.getLocationPointOfInterestId() != null)).forEach((o) -> {
locationPointOfInterestIds.add(o.getLocationPointOfInterestId());
Set<Integer> locationPointOfInterestIds = new HashSet<>();
observations.stream().filter((o) -> (o.getLocationPointOfInterestId() != null)).forEach((o) -> {
locationPointOfInterestIds.add(o.getLocationPointOfInterestId());
});
// Nothing to do?
if(locationPointOfInterestIds.isEmpty())
{
// Nothing to do?
if (locationPointOfInterestIds.isEmpty()) {
return observations;
}
List<PointOfInterest> pois = pointOfInterestBean.getPois(locationPointOfInterestIds);
Map<Integer, PointOfInterest> mappedPois = new HashMap<>();
pois.stream().forEach((poi) -> {
mappedPois.put(poi.getPointOfInterestId(), poi);
List<PointOfInterest> pois = pointOfInterestBean.getPois(locationPointOfInterestIds);
Map<Integer, PointOfInterest> mappedPois = new HashMap<>();
pois.stream().forEach((poi) -> {
mappedPois.put(poi.getPointOfInterestId(), poi);
});
observations.stream().filter((o) -> (o.getLocationPointOfInterestId() != null)).forEach((o) -> {
o.setLocation(mappedPois.get(o.getLocationPointOfInterestId()));
observations.stream().filter((o) -> (o.getLocationPointOfInterestId() != null)).forEach((o) -> {
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) {
Set<Integer> userIds = new HashSet<>();
observations.stream().filter((o) -> (o.getUserId() != null)).forEach((o) -> {
userIds.add(o.getUserId());
});
// Nothing to do?
if(userIds.isEmpty())
{
if (userIds.isEmpty()) {
return observations;
}
List<VipsLogicUser> users = userBean.getUsers(userIds);
Map<Integer, VipsLogicUser> mappedUsers = new HashMap<>();
users.stream().forEach((user) -> {
mappedUsers.put(user.getUserId(), user);
List<VipsLogicUser> users = userBean.getUsers(userIds);
Map<Integer, VipsLogicUser> mappedUsers = new HashMap<>();
users.stream().forEach((user) -> {
mappedUsers.put(user.getUserId(), user);
});
observations.stream().filter((o) -> (o.getUserId() != null)).forEach((o) -> {
o.setUser(mappedUsers.get(o.getUserId()));
observations.stream().filter((o) -> (o.getUserId() != null)).forEach((o) -> {
o.setUser(mappedUsers.get(o.getUserId()));
});
return observations;
}
public List<Observation> getObservationsOfPest(Integer pestOrganismId)
{
List <Observation> observations =
em.createNamedQuery("Observation.findByOrganism")
.setParameter("organism", em.find(Organism.class, pestOrganismId))
.getResultList();
public List<Observation> getObservationsOfPest(Integer pestOrganismId) {
List<Observation> observations =
em.createNamedQuery("Observation.findByOrganism")
.setParameter("organism", em.find(Organism.class, pestOrganismId))
.getResultList();
observations = this.getObservationsWithGeoInfo(observations);
observations = this.getObservationsWithLocations(observations);
observations = getObservationsWithObservers(observations);
return observations;
}
public List<Observation> getObservationsOfPestForUser(VipsLogicUser user, Integer pestOrganismId)
{
List <Observation> observations =
em.createNamedQuery("Observation.findByUserIdAndOrganism")
.setParameter("userId", user.getUserId())
.setParameter("organism", em.find(Organism.class, pestOrganismId))
.getResultList();
public List<Observation> getObservationsOfPestForUser(VipsLogicUser user, Integer pestOrganismId) {
List<Observation> observations =
em.createNamedQuery("Observation.findByUserIdAndOrganism")
.setParameter("userId", user.getUserId())
.setParameter("organism", em.find(Organism.class, pestOrganismId))
.getResultList();
observations = this.getObservationsWithGeoInfo(observations);
observations = this.getObservationsWithLocations(observations);
observations = this.getObservationsWithObservers(observations);
......@@ -604,98 +588,99 @@ public class ObservationBean {
}
public List<Observation> getFilteredObservations(
Integer organizationId,
Integer pestId,
Integer cropId,
Integer organizationId,
Integer observationTimeSeriesId,
Integer pestId,
Integer cropId,
List<Integer> cropCategoryId,
Date from,
Date from,
Date to,
Boolean isPositive
)
{
Boolean isPositive) {
// The minimum SQL
String sql = "SELECT * FROM public.observation \n" +
"WHERE status_type_id = :statusTypeId \n " +
"AND user_id IN (SELECT user_id FROM public.vips_logic_user WHERE organization_id = :organizationId) \n";
"WHERE status_type_id = :statusTypeId \n " +
"AND user_id IN (SELECT user_id FROM public.vips_logic_user WHERE organization_id = :organizationId) \n";
Map<String, Object> parameters = new HashMap<>();
parameters.put("statusTypeId", ObservationStatusType.STATUS_APPROVED);
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
if(pestId != null && pestId > 0)
{
if (pestId != null && pestId > 0) {
sql += "AND organism_id = :organismId \n";
parameters.put("organismId", pestId);
}
// Filter either for crop or cropCategoryId
if(cropId != null && cropId > 0)
{
if (cropId != null && cropId > 0) {
sql += "AND crop_organism_id = :cropOrganismId \n";
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)
.setParameter("cropCategoryIds", cropCategoryId)
.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";
parameters.put("cropOrganismIds", cropIds);
//parameters.put("cropOrganismIds", List.of(5));
}
// Filter for dates
if(from != null)
{
if (from != null) {
sql += "AND time_of_observation >= :from \n";
parameters.put("from", from);
}
if(to != null)
{
if (to != null) {
sql += "AND time_of_observation <= :to \n";
parameters.put("to", to);
}
// Filter for positive/negative registrations
if(isPositive != null)
{
if (isPositive != null) {
sql += "AND is_positive = :isPositive \n";
parameters.put("isPositive", isPositive);
}
sql += "ORDER BY time_of_observation DESC, observation_id DESC";
LOGGER.debug(sql);
Query q = em.createNativeQuery(sql, Observation.class);
// Setting the parameters one by one
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();
List<Observation> observations = q.getResultList();
//System.out.println("Finding obs took " + (new Date().getTime() - start.getTime()) + " milliseconds");
//start = new Date();
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");
List<Observation> retVal = new ArrayList<>();
if(! observations.isEmpty())
{
if (!observations.isEmpty()) {
//Date start = new Date();
retVal = this.getObservationsWithGeoInfo(observations);
//System.out.println("Finding geoinfo took " + (new Date().getTime() - start.getTime()) + " milliseconds");
//start = new Date();
retVal = this.getObservationsWithLocations(retVal);
//System.out.println("Finding locations took " + (new Date().getTime() - start.getTime()) + " milliseconds");
retVal = this.getObservationsWithTimeSeries(retVal);
}
return retVal;
}
public List<Organism> getObservedPests(Integer organizationId) {
......@@ -706,9 +691,9 @@ public class ObservationBean {
return em.createNamedQuery("Organism.findByOrganismIds")
.setParameter("organismIds", pestIds)
.getResultList();
}
public List<Organism> getObservedCrops(Integer organizationId) {
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"
......@@ -717,7 +702,7 @@ public class ObservationBean {
return em.createNamedQuery("Organism.findByOrganismIds")
.setParameter("organismIds", cropIds)
.getResultList();
}
public Observation getObservationFromGeoJSON(String geoJSON) throws IOException {
......@@ -727,23 +712,22 @@ public class ObservationBean {
Map<String, Object> properties = firstAndBest.getProperties();
Observation observation = new Observation();
Integer observationId = (Integer) properties.get("observationId");
if(observationId > 0)
{
if (observationId > 0) {
observation = em.find(Observation.class, observationId);
}
observation.setObservationData((String) properties.get("observationData"));
ObjectMapper mapper = new ObjectMapper();
observation.setCropOrganism(mapper.convertValue(properties.get("cropOrganism"), Organism.class));
observation.setOrganism(mapper.convertValue(properties.get("organism"), Organism.class));
observation.setObservationHeading((String)properties.get("observationHeading"));
observation.setObservationText((String)properties.get("observationText"));
observation.setObservationHeading((String) properties.get("observationHeading"));
observation.setObservationText((String) properties.get("observationText"));
observation.setTimeOfObservation(new Date((Long) properties.get("timeOfObservation")));
observation.setGeoinfo(geoJSON);
observation.setStatusTypeId((Integer) properties.get("statusTypeId"));
observation.setStatusRemarks((String) properties.get("statusRemarks"));
observation.setIsQuantified((Boolean) properties.get("isQuantified"));
observation.setBroadcastMessage((Boolean) properties.get("broadcastMessage"));
return observation;
return observation;
}
public void deleteGisObservationByGis(Integer gisId) {
......@@ -759,41 +743,34 @@ public class ObservationBean {
.getResultList();
}
public List<Integer> getOrganizationGroupIds(Observation observation) {
if(observation.getObservationId() != null)
{
public List<Integer> getOrganizationGroupIds(Observation observation) {
if (observation.getObservationId() != null) {
return em.createNativeQuery("SELECT organization_group_id FROM public.organization_group_observation "
+ "WHERE observation_id = :observationId")
+ "WHERE observation_id = :observationId")
.setParameter("observationId", observation.getObservationId())
.getResultList();
}
else
{
} else {
return new ArrayList<>();
}
}
public void storeOrganizationGroupObservationIds(Observation obs, String[] organizationGroupIds) {
// First delete all current group memberships
em.createNativeQuery("DELETE FROM public.organization_group_observation WHERE observation_id=:observationId")
.setParameter("observationId", obs.getObservationId())
.executeUpdate();
if(organizationGroupIds != null)
{
if (organizationGroupIds != null) {
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());
// Then add
for(String groupIdStr:organizationGroupIds)
{
for (String groupIdStr : organizationGroupIds) {
try {
Integer groupId = Integer.valueOf(groupIdStr);
q.setParameter("organizationGroupId", groupId);
q.executeUpdate();
}
catch(NumberFormatException ex)
{
} catch (NumberFormatException ex) {
// Continue
}
}
......@@ -802,30 +779,27 @@ public class ObservationBean {
/**
* Returns the first time an observation of the given pest registered in the system was made
*
* @param organismId
* @return
* @return
*/
public Date getFirstObservationTime(Integer organismId) {
try
{
List<Observation> obs = em.createNamedQuery("Observation.findFirstByOrganism")
try {
List<Observation> obs = em.createNamedQuery("Observation.findFirstByOrganism")
.setParameter("organism", em.find(Organism.class, organismId))
.getResultList();
return obs.get(0).getTimeOfObservation();
}
catch(NoResultException | IndexOutOfBoundsException ex)
{
} catch (NoResultException | IndexOutOfBoundsException ex) {
return null;
}
}
public PolygonService getPolygonService(Integer polygonServiceId)
{
return em.find(PolygonService.class, polygonServiceId);
public PolygonService getPolygonService(Integer polygonServiceId) {
return em.find(PolygonService.class, polygonServiceId);
}
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)
.setParameter("organizationId", organizationId)
......@@ -840,7 +814,8 @@ public class ObservationBean {
/**
* Part of the cleaning up dependencies procedure for when deleting a POI
* @param poi
*
* @param poi
*/
public void deleteObservationsForLocation(PointOfInterest poi) {
em.createNamedQuery("Observation.findByLocationPointOfInterestId", Observation.class)
......@@ -848,99 +823,96 @@ public class ObservationBean {
.getResultList().stream()
.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)
*
* @param organizationId
* @param organismId
* @param httpServletRequest
* @return
* @return
*/
public ObservationDataSchema getObservationDataSchema(Integer organizationId, Integer organismId)
{
try
{
public ObservationDataSchema getObservationDataSchema(Integer organizationId, Integer organismId) {
try {
return em.createNamedQuery("ObservationDataSchema.findByPK", ObservationDataSchema.class)
.setParameter("organizationId", organizationId)
.setParameter("organismId", organismId)
.getSingleResult();
}
catch(NoResultException ex)
{
.setParameter("organizationId", organizationId)
.setParameter("organismId", organismId)
.getSingleResult();
} catch (NoResultException ex) {
//System.out.println("Could not find schema for orgId " + organizationId + " and organismId " + organismId);
return this.getStandardSchema(organizationId);
}
}
/**
* If there exist title translations for this schema, it
*
* @param schema
* @param httpServletRequest
* @return
* @return
*/
public ObservationDataSchema getLocalizedObservationDataSchema(ObservationDataSchema ods, HttpServletRequest httpServletRequest, ULocale locale) throws IOException
{
if(locale != null)
{
SessionLocaleUtil.setCurrentLocale(httpServletRequest, locale);
public ObservationDataSchema getLocalizedObservationDataSchema(ObservationDataSchema ods, HttpServletRequest httpServletRequest, ULocale locale) throws IOException {
if (locale != null) {
SessionLocaleUtil.setCurrentLocale(httpServletRequest, locale);
}
ResourceBundle bundle = SessionLocaleUtil.getI18nBundle(httpServletRequest);
// We iterate the schema, replacing default field labels with
// translated ones
// First: Convert to Jackson JsonNode tree
ObjectMapper m = new ObjectMapper();
JsonNode rootNode = m.readTree(ods.getDataSchema());
// Is this the full schema or just the "properties" property?
JsonNode propertiesNode = rootNode.get("properties") == null ? rootNode : rootNode.get("properties");
Iterator<Entry<String, JsonNode>> nodeIterator = propertiesNode.fields();
String fieldKeyPrefix = "observationDataField_";
// Loop through each field
while (nodeIterator.hasNext()) {
Map.Entry<String, JsonNode> schemaPropertyField = (Map.Entry<String, JsonNode>) nodeIterator.next();
// Get the property field key (e.g. "counting2")
String fieldKey = schemaPropertyField.getKey();
// Find a translation.
if(bundle.containsKey(fieldKeyPrefix + fieldKey))
{
// If found, replace with translation
// Get the property field (e.g. {"title":"Counting 2"} )
JsonNode schemaProperty = schemaPropertyField.getValue();
((ObjectNode)schemaProperty).put("title", bundle.getString(fieldKeyPrefix + fieldKey));
((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;
// We iterate the schema, replacing default field labels with
// translated ones
// First: Convert to Jackson JsonNode tree
ObjectMapper m = new ObjectMapper();
JsonNode rootNode = m.readTree(ods.getDataSchema());
// Is this the full schema or just the "properties" property?
JsonNode propertiesNode = rootNode.get("properties") == null ? rootNode : rootNode.get("properties");
Iterator<Entry<String, JsonNode>> nodeIterator = propertiesNode.fields();
String fieldKeyPrefix = "observationDataField_";
// Loop through each field
while (nodeIterator.hasNext()) {
Map.Entry<String, JsonNode> schemaPropertyField = (Map.Entry<String, JsonNode>) nodeIterator.next();
// Get the property field key (e.g. "counting2")
String fieldKey = schemaPropertyField.getKey();
// Find a translation.
if (bundle.containsKey(fieldKeyPrefix + fieldKey)) {
// If found, replace with translation
// Get the property field (e.g. {"title":"Counting 2"} )
JsonNode schemaProperty = schemaPropertyField.getValue();
((ObjectNode) schemaProperty).put("title", bundle.getString(fieldKeyPrefix + fieldKey));
((ObjectNode) propertiesNode).replace(fieldKey, schemaProperty);
}
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
* @return
* @return
*/
private ObservationDataSchema getStandardSchema(Integer organizationId){
private ObservationDataSchema getStandardSchema(Integer organizationId) {
ObservationDataSchema retVal = new ObservationDataSchema();
retVal.setDataSchema("{\n"
+ " \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n"
+ " \"type\": \"object\",\n"
+ " \"title\": \"Default schema\",\n"
+ " \"properties\": {"
+ " \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n"
+ " \"type\": \"object\",\n"
+ " \"title\": \"Default schema\",\n"
+ " \"properties\": {"
+ "\"number\":{\"title\":\"Number\"},"
+ "\"unit\":{\"title\":\"Unit\"}"
+ "}"
......@@ -955,7 +927,6 @@ public class ObservationBean {
retVal.setObservationDataSchemaPK(pk);
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;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import jakarta.ejb.Stateless;
import jakarta.persistence.EntityManager;
import jakarta.persistence.NoResultException;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;
import no.nibio.vips.logic.entity.CropCategory;
import no.nibio.vips.logic.entity.CropPest;
import no.nibio.vips.logic.entity.DbUpdate;
......@@ -419,7 +419,7 @@ public class OrganismBean {
cropCategories.stream()
.filter((cc) -> (cc.getCropOrganismIds() != null))
.forEachOrdered((cc) -> {
retVal.addAll(Arrays.asList(cc.getCropOrganismIds()));
retVal.addAll(cc.getCropOrganismIds());
});
return retVal;
......
......@@ -33,13 +33,13 @@ import java.util.List;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.stream.Collectors;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import jakarta.ejb.EJB;
import jakarta.ejb.LocalBean;
import jakarta.ejb.Stateless;
import jakarta.persistence.EntityManager;
import jakarta.persistence.NoResultException;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;
import no.nibio.vips.gis.GISUtil;
import no.nibio.vips.logic.entity.ExternalResource;
import no.nibio.vips.logic.entity.ExternalResourceType;
......@@ -263,10 +263,54 @@ public class PointOfInterestBean {
return kml;
}
public WeatherStationDataSource getWeatherStationDataSource(Integer weatherStationDataSourceId)
{
return em.find(WeatherStationDataSource.class, weatherStationDataSourceId);
}
public List<WeatherStationDataSource> getWeatherStationDataSources() {
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) {
weatherStation = em.merge(weatherStation);
return weatherStation;
......
......@@ -37,16 +37,16 @@ import java.util.Set;
import java.util.SortedMap;
import java.util.TimeZone;
import java.util.TreeMap;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
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 jakarta.ejb.EJB;
import jakarta.ejb.Stateless;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;
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 no.nibio.vips.coremanager.service.ManagerResource;
import no.nibio.vips.entity.ModelConfiguration;
import no.nibio.vips.entity.ModelRunRequest;
......@@ -217,9 +217,6 @@ public class SchedulingBean {
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<>();
definedTasks.add(modelRunCollector);
......@@ -227,7 +224,6 @@ public class SchedulingBean {
definedTasks.add(summariesCollector);
definedTasks.add(deleteAllExpiredUserUuidsCollector);
definedTasks.add(sendForecastNotificationsCollector);
definedTasks.add(runGridModelsCollector);
return definedTasks;
}
......
......@@ -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!
* @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>
*/
......@@ -34,7 +34,7 @@ public class SessionControllerGetter {
// 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)
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()
{
......
......@@ -41,14 +41,14 @@ import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.*;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.ws.rs.core.HttpHeaders;
import jakarta.ejb.EJB;
import jakarta.ejb.LocalBean;
import jakarta.ejb.Stateless;
import jakarta.persistence.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import jakarta.ws.rs.core.HttpHeaders;
import no.nibio.vips.logic.authenticate.PasswordValidationException;
import no.nibio.vips.logic.entity.*;
......
......@@ -21,19 +21,19 @@ package no.nibio.vips.logic.entity;
import java.io.Serializable;
import java.util.Locale;
import java.util.Set;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import jakarta.persistence.Basic;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.NamedQueries;
import jakarta.persistence.NamedQuery;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import com.fasterxml.jackson.annotation.JsonIgnore;
......
......@@ -19,27 +19,28 @@
package no.nibio.vips.logic.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.hypersistence.utils.hibernate.type.array.ListArrayType;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.stream.Collectors;
import jakarta.persistence.Basic;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.NamedQueries;
import jakarta.persistence.NamedQuery;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
import no.nibio.vips.logic.util.IntegerArrayUserType;
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>
......@@ -48,7 +49,6 @@ import org.hibernate.annotations.TypeDefs;
@Entity
@Table(name = "crop_category")
@XmlRootElement
@TypeDefs( {@TypeDef( name= "IntegerArray", typeClass = IntegerArrayUserType.class)})
@NamedQueries({
@NamedQuery(name = "CropCategory.findAll", query = "SELECT c FROM CropCategory c"),
@NamedQuery(name = "CropCategory.findByCropCategoryId", query = "SELECT c FROM CropCategory c WHERE c.cropCategoryId = :cropCategoryId"),
......@@ -70,9 +70,9 @@ public class CropCategory implements Serializable {
private String defaultName;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "cropCategoryId", fetch = FetchType.EAGER)
private Set<CropCategoryLocal> cropCategoryLocalSet;
@Type(type = "IntegerArray")
@Column(name = "crop_organism_ids")
private Integer[] cropOrganismIds;
@Type(ListArrayType.class)
private List<Integer> cropOrganismIds;
@Column(name = "organization_id")
private Integer organizationId;
@Column(name = "max_hierarchy_category_id")
......@@ -101,11 +101,11 @@ public class CropCategory implements Serializable {
this.defaultName = defaultName;
}
public Integer[] getCropOrganismIds() {
public List<Integer> getCropOrganismIds() {
return cropOrganismIds;
}
public void setCropOrganismIds(Integer[] cropOrganismIds) {
public void setCropOrganismIds(List<Integer> cropOrganismIds) {
this.cropOrganismIds = cropOrganismIds;
}
......@@ -203,18 +203,18 @@ public class CropCategory implements Serializable {
}
else
{
cropSet = new HashSet<>(Arrays.asList(this.getCropOrganismIds()));
cropSet = new HashSet<>(this.getCropOrganismIds());
}
cropSet.add(organismId);
this.setCropOrganismIds(cropSet.toArray(new Integer[cropSet.size()]));
this.setCropOrganismIds(cropSet.stream().collect(Collectors.toList()));
}
public void removeCropOrganismId(Integer organismId) {
if(this.getCropOrganismIds() != null)
{
Set<Integer> cropSet = new HashSet<>(Arrays.asList(this.getCropOrganismIds()));
Set<Integer> cropSet = new HashSet<>(this.getCropOrganismIds());
cropSet.remove(organismId);
this.setCropOrganismIds(cropSet.toArray(new Integer[cropSet.size()]));
this.setCropOrganismIds(cropSet.stream().collect(Collectors.toList()));
}
}
......
......@@ -19,13 +19,13 @@
package no.nibio.vips.logic.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.validation.constraints.Size;
import jakarta.persistence.Column;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import jakarta.persistence.NamedQueries;
import jakarta.persistence.NamedQuery;
import jakarta.persistence.Table;
import jakarta.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
/**
......
......@@ -19,11 +19,11 @@
package no.nibio.vips.logic.entity;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import jakarta.persistence.Basic;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
/**
* @copyright 2016 <a href="http://www.nibio.no/">NIBIO</a>
......
......@@ -19,19 +19,18 @@
package no.nibio.vips.logic.entity;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import java.util.List;
import jakarta.persistence.Basic;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.NamedQueries;
import jakarta.persistence.NamedQuery;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import javax.xml.bind.annotation.XmlRootElement;
import no.nibio.vips.logic.util.IntegerArrayUserType;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.hibernate.annotations.TypeDefs;
import io.hypersistence.utils.hibernate.type.array.ListArrayType;
/**
* @copyright 2016 <a href="http://www.nibio.no/">NIBIO</a>
......@@ -39,7 +38,6 @@ import org.hibernate.annotations.TypeDefs;
*/
@Entity
@Table(name = "crop_pest")
@TypeDefs( {@TypeDef( name= "IntegerArray", typeClass = IntegerArrayUserType.class)})
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "CropPest.findAll", query = "SELECT c FROM CropPest c"),
......@@ -55,9 +53,9 @@ public class CropPest implements Serializable {
@NotNull
@Column(name = "crop_organism_id")
private Integer cropOrganismId;
@Type(type = "IntegerArray")
@Type(ListArrayType.class)
@Column(name = "pest_organism_ids")
private Integer[] pestOrganismIds;
private List<Integer> pestOrganismIds;
@Column(name = "include_all_child_crops")
private Boolean includeAllChildCrops;
......@@ -76,11 +74,11 @@ public class CropPest implements Serializable {
this.cropOrganismId = cropOrganismId;
}
public Integer[] getPestOrganismIds() {
public List<Integer> getPestOrganismIds() {
return pestOrganismIds;
}
public void setPestOrganismIds(Integer[] pestOrganismIds) {
public void setPestOrganismIds(List<Integer> pestOrganismIds) {
this.pestOrganismIds = pestOrganismIds;
}
......
......@@ -20,16 +20,16 @@ package no.nibio.vips.logic.entity;
import java.io.Serializable;
import java.util.Collection;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import jakarta.persistence.Basic;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.NamedQueries;
import jakarta.persistence.NamedQuery;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
......
......@@ -20,17 +20,17 @@ package no.nibio.vips.logic.entity;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import jakarta.persistence.Basic;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.NamedQueries;
import jakarta.persistence.NamedQuery;
import jakarta.persistence.Table;
import jakarta.persistence.Temporal;
import jakarta.persistence.TemporalType;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
/**
......
......@@ -20,21 +20,21 @@ package no.nibio.vips.logic.entity;
import java.io.Serializable;
import java.util.Set;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.Size;
import jakarta.persistence.Basic;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.NamedQueries;
import jakarta.persistence.NamedQuery;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import com.fasterxml.jackson.annotation.JsonIgnore;
......