From eb28aad4321b1ae0b8dd69cdab0ba440d2979f01 Mon Sep 17 00:00:00 2001
From: Tor-Einar Skog <tor-einar.skog@nibio.no>
Date: Tue, 11 Mar 2025 15:50:51 +0100
Subject: [PATCH] Fix: return only public weatherstations unless stated
 otherwise

---
 .../NotificationSubscriptionController.java   |  4 +-
 .../servlet/PointOfInterestController.java    | 36 ++++++-------
 .../session/PointOfInterestBean.java          | 35 +++++++------
 ...castConfigurationsForOrganizationTask.java |  8 +--
 .../vips/logic/service/LogicService.java      |  2 +-
 .../nibio/vips/logic/service/POIService.java  | 50 +++++++++++--------
 6 files changed, 68 insertions(+), 67 deletions(-)

diff --git a/src/main/java/no/nibio/vips/logic/controller/servlet/NotificationSubscriptionController.java b/src/main/java/no/nibio/vips/logic/controller/servlet/NotificationSubscriptionController.java
index d8cb4769..ca77ed89 100755
--- a/src/main/java/no/nibio/vips/logic/controller/servlet/NotificationSubscriptionController.java
+++ b/src/main/java/no/nibio/vips/logic/controller/servlet/NotificationSubscriptionController.java
@@ -17,11 +17,11 @@
  */
 package no.nibio.vips.logic.controller.servlet;
 
-import freemarker.core.ParseException;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
 import java.util.List;
+import freemarker.core.ParseException;
 import jakarta.ejb.EJB;
 import jakarta.persistence.EntityManager;
 import jakarta.persistence.PersistenceContext;
@@ -127,7 +127,7 @@ public class NotificationSubscriptionController extends HttpServlet {
                         );
                 request.setAttribute("allCropCategories", allCropCategories);
                 request.setAttribute("messageTagSet", em.createNamedQuery("MessageTag.findAll").getResultList());
-                request.setAttribute("weatherStationIds", pointOfInterestBean.getWeatherstationsForOrganization(viewUser.getOrganizationId(), true));
+                request.setAttribute("weatherStationIds", pointOfInterestBean.getWeatherstationsForOrganization(viewUser.getOrganizationId(), true, Boolean.TRUE));
                 request.setAttribute("universalMessageFormats", messagingBean.getAllUniversalMessageFormats());
                 request.setAttribute("messageKey", request.getParameter("messageKey"));
                 request.getRequestDispatcher("/notificationSubscriptionForm.ftl").forward(request, response);
diff --git a/src/main/java/no/nibio/vips/logic/controller/servlet/PointOfInterestController.java b/src/main/java/no/nibio/vips/logic/controller/servlet/PointOfInterestController.java
index d8833ffd..b296e0e5 100755
--- a/src/main/java/no/nibio/vips/logic/controller/servlet/PointOfInterestController.java
+++ b/src/main/java/no/nibio/vips/logic/controller/servlet/PointOfInterestController.java
@@ -18,15 +18,16 @@
 
 package no.nibio.vips.logic.controller.servlet;
 
-import org.locationtech.jts.geom.Coordinate;
-import org.locationtech.jts.geom.GeometryFactory;
-import org.locationtech.jts.geom.Point;
 import java.io.IOException;
 import java.net.URISyntaxException;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import org.apache.http.client.utils.URIBuilder;
+import org.locationtech.jts.geom.Coordinate;
+import org.locationtech.jts.geom.GeometryFactory;
+import org.locationtech.jts.geom.Point;
 import jakarta.ejb.EJB;
 import jakarta.persistence.EntityManager;
 import jakarta.persistence.PersistenceContext;
@@ -34,9 +35,15 @@ import jakarta.servlet.ServletException;
 import jakarta.servlet.http.HttpServlet;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
+import no.nibio.vips.gis.GISUtil;
+import no.nibio.vips.logic.controller.session.ForecastBean;
+import no.nibio.vips.logic.controller.session.ObservationBean;
+import no.nibio.vips.logic.controller.session.PointOfInterestBean;
+import no.nibio.vips.logic.controller.session.UserBean;
 import no.nibio.vips.logic.entity.Country;
 import no.nibio.vips.logic.entity.ForecastConfiguration;
 import no.nibio.vips.logic.entity.ModelInformation;
+import no.nibio.vips.logic.entity.Observation;
 import no.nibio.vips.logic.entity.Organization;
 import no.nibio.vips.logic.entity.PointOfInterest;
 import no.nibio.vips.logic.entity.PointOfInterestExternalResource;
@@ -44,25 +51,18 @@ import no.nibio.vips.logic.entity.PointOfInterestExternalResourcePK;
 import no.nibio.vips.logic.entity.PointOfInterestWeatherStation;
 import no.nibio.vips.logic.entity.VipsLogicRole;
 import no.nibio.vips.logic.entity.VipsLogicUser;
-import no.nibio.vips.logic.entity.WeatherStationDataSource;
-import no.nibio.vips.util.ExceptionUtil;
-import no.nibio.vips.util.ServletUtil;
 import no.nibio.vips.logic.entity.WeatherForecastProvider;
-import no.nibio.vips.logic.i18n.SessionLocaleUtil;
-import no.nibio.vips.gis.GISUtil;
-import no.nibio.vips.logic.controller.session.ForecastBean;
-import no.nibio.vips.logic.controller.session.ObservationBean;
-import no.nibio.vips.logic.controller.session.PointOfInterestBean;
-import no.nibio.vips.logic.controller.session.UserBean;
-import no.nibio.vips.logic.entity.Observation;
+import no.nibio.vips.logic.entity.WeatherStationDataSource;
 import no.nibio.vips.logic.entity.helpers.PointOfInterestFactory;
+import no.nibio.vips.logic.i18n.SessionLocaleUtil;
 import no.nibio.vips.logic.util.Globals;
 import no.nibio.vips.logic.util.SystemTime;
+import no.nibio.vips.util.ExceptionUtil;
+import no.nibio.vips.util.ServletUtil;
 import no.nibio.web.forms.FormField;
 import no.nibio.web.forms.FormValidation;
 import no.nibio.web.forms.FormValidationException;
 import no.nibio.web.forms.FormValidator;
-import org.apache.http.client.utils.URIBuilder;
 
 /**
  * Handles transactions for POIs
@@ -133,8 +133,8 @@ public class PointOfInterestController extends HttpServlet {
                         else
                         {
                             organization = em.find(Organization.class, organizationId);
-                            activeWeatherStations = pointOfInterestBean.getWeatherstationsForOrganization(organization, true);
-                            inactiveWeatherStations = pointOfInterestBean.getWeatherstationsForOrganization(organization, false);
+                            activeWeatherStations = pointOfInterestBean.getWeatherstationsForOrganization(organization, true, true);
+                            inactiveWeatherStations = pointOfInterestBean.getWeatherstationsForOrganization(organization, false, true);
                         }
                         request.setAttribute("organizations", userBean.getOrganizations());
                         request.setAttribute("organizationId", organizationId);
@@ -143,8 +143,8 @@ public class PointOfInterestController extends HttpServlet {
                     else
                     {
                         organization = user.getOrganizationId();
-                        activeWeatherStations = pointOfInterestBean.getWeatherstationsForOrganization(organization,true);
-                        inactiveWeatherStations = pointOfInterestBean.getWeatherstationsForOrganization(organization, false);
+                        activeWeatherStations = pointOfInterestBean.getWeatherstationsForOrganization(organization,true, false);
+                        inactiveWeatherStations = pointOfInterestBean.getWeatherstationsForOrganization(organization, false, false);
                         request.setAttribute("organizationId", organization.getOrganizationId());
                     }
                     
diff --git a/src/main/java/no/nibio/vips/logic/controller/session/PointOfInterestBean.java b/src/main/java/no/nibio/vips/logic/controller/session/PointOfInterestBean.java
index 5a4cd503..b064c913 100755
--- a/src/main/java/no/nibio/vips/logic/controller/session/PointOfInterestBean.java
+++ b/src/main/java/no/nibio/vips/logic/controller/session/PointOfInterestBean.java
@@ -18,6 +18,15 @@
 
 package no.nibio.vips.logic.controller.session;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.wololo.geojson.Feature;
+import org.wololo.geojson.GeoJSON;
+import org.wololo.jts2geojson.GeoJSONWriter;
 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;
@@ -26,13 +35,6 @@ import de.micromata.opengis.kml.v_2_2_0.Kml;
 import de.micromata.opengis.kml.v_2_2_0.KmlFactory;
 import de.micromata.opengis.kml.v_2_2_0.Placemark;
 import de.micromata.opengis.kml.v_2_2_0.Point;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.ResourceBundle;
-import java.util.Set;
-import java.util.stream.Collectors;
 import jakarta.ejb.EJB;
 import jakarta.ejb.LocalBean;
 import jakarta.ejb.Stateless;
@@ -53,11 +55,6 @@ import no.nibio.vips.logic.entity.VipsLogicUser;
 import no.nibio.vips.logic.entity.WeatherStationDataSource;
 import no.nibio.vips.logic.util.GISEntityUtil;
 import no.nibio.vips.logic.util.Globals;
-import org.wololo.geojson.Feature;
-import org.wololo.geojson.FeatureCollection;
-import org.wololo.geojson.GeoJSON;
-import org.wololo.geojson.GeoJSONFactory;
-import org.wololo.jts2geojson.GeoJSONWriter;
 
 
 /**
@@ -174,7 +171,7 @@ public class PointOfInterestBean {
             {
                 if(pointOfInterestTypeId != null && pointOfInterestTypeId == PointOfInterestType.POINT_OF_INTEREST_TYPE_WEATHER_STATION)
                 {
-                    pois.addAll(this.getWeatherstationsForOrganization(organization,true));
+                    pois.addAll(this.getWeatherstationsForOrganization(organization,true, false));
                 }
                 else
                 {
@@ -186,7 +183,7 @@ public class PointOfInterestBean {
         {
             if(pointOfInterestTypeId != null && pointOfInterestTypeId == PointOfInterestType.POINT_OF_INTEREST_TYPE_WEATHER_STATION)
             {
-                pois.addAll(this.getWeatherstationsForOrganization(em.find(Organization.class, organizationId),true));
+                pois.addAll(this.getWeatherstationsForOrganization(em.find(Organization.class, organizationId),true, false));
             }
             else
             {
@@ -320,9 +317,9 @@ public class PointOfInterestBean {
      * 
      * @param organization
      * @param active
-     * @return 
+     * @return public weather stations for an organization
      */
-    public List<PointOfInterestWeatherStation> getWeatherstationsForOrganization(Organization organization, Boolean active) {
+    public List<PointOfInterestWeatherStation> getWeatherstationsForOrganization(Organization organization, Boolean active, Boolean includePrivate) {
         
         if(organization == null)
         {
@@ -342,7 +339,9 @@ public class PointOfInterestBean {
                                 .getResultList()
             );
         }
-        return retVal;
+
+        // Only public weather stations in this list UNLESS explicitly stated otherwise     
+        return (includePrivate != null && includePrivate) ? retVal: retVal.stream().filter(poi-> ! poi.getIsPrivate()).collect(Collectors.toList());
     }
 
     public List<ExternalResource> getUnusedExternalResourcesForPointOfInterest(PointOfInterest weatherStation) {
@@ -522,7 +521,7 @@ public class PointOfInterestBean {
             catch(NoResultException ex) {}
             // Getting all weather stations for user's organization. Need to avoid
             // double catching of privately owned weather station
-            retVal.addAll(this.getWeatherstationsForOrganization(user.getOrganizationId(), Boolean.TRUE)
+            retVal.addAll(this.getWeatherstationsForOrganization(user.getOrganizationId(), Boolean.TRUE, Boolean.FALSE)
                     .stream()
                     .filter(weatherStation -> ! weatherStation.getUser().getUserId().equals(user.getUserId()))
                     .collect(Collectors.toList())
diff --git a/src/main/java/no/nibio/vips/logic/scheduling/tasks/RunAllForecastConfigurationsForOrganizationTask.java b/src/main/java/no/nibio/vips/logic/scheduling/tasks/RunAllForecastConfigurationsForOrganizationTask.java
index 6b1ec301..66be66c3 100644
--- a/src/main/java/no/nibio/vips/logic/scheduling/tasks/RunAllForecastConfigurationsForOrganizationTask.java
+++ b/src/main/java/no/nibio/vips/logic/scheduling/tasks/RunAllForecastConfigurationsForOrganizationTask.java
@@ -18,16 +18,12 @@
 
 package no.nibio.vips.logic.scheduling.tasks;
 
-import it.sauronsoftware.cron4j.TaskExecutionContext;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import jakarta.ejb.EJB;
+import it.sauronsoftware.cron4j.TaskExecutionContext;
 import no.nibio.vips.i18n.I18nImpl;
-import no.nibio.vips.logic.controller.session.ForecastBean;
-import no.nibio.vips.logic.controller.session.PointOfInterestBean;
 import no.nibio.vips.logic.controller.session.SessionControllerGetter;
-import no.nibio.vips.logic.controller.session.UserBean;
 import no.nibio.vips.logic.entity.ForecastConfiguration;
 import no.nibio.vips.logic.entity.ModelInformation;
 import no.nibio.vips.logic.entity.PointOfInterest;
@@ -134,7 +130,7 @@ public class RunAllForecastConfigurationsForOrganizationTask extends RunAllForec
                     .append("\",\"selected\":")
                     .append("false")
                     .append("}\n");
-        List<PointOfInterestWeatherStation> stations = SessionControllerGetter.getPointOfInterestBean().getWeatherstationsForOrganization(this.getOrganization(), Boolean.TRUE);
+        List<PointOfInterestWeatherStation> stations = SessionControllerGetter.getPointOfInterestBean().getWeatherstationsForOrganization(this.getOrganization(), Boolean.TRUE, Boolean.TRUE);
         Collections.sort(stations);
         for(PointOfInterest station:stations)
         {
diff --git a/src/main/java/no/nibio/vips/logic/service/LogicService.java b/src/main/java/no/nibio/vips/logic/service/LogicService.java
index 98a30fb6..ed24e8cf 100755
--- a/src/main/java/no/nibio/vips/logic/service/LogicService.java
+++ b/src/main/java/no/nibio/vips/logic/service/LogicService.java
@@ -810,7 +810,7 @@ public class LogicService {
     public Response getPoisForOrganization(@PathParam("organizationId") Integer organizationId)
     {
         Organization organization = userBean.getOrganization(organizationId);
-        List<PointOfInterestWeatherStation> retVal = pointOfInterestBean.getWeatherstationsForOrganization(organization, Boolean.TRUE);
+        List<PointOfInterestWeatherStation> retVal = pointOfInterestBean.getWeatherstationsForOrganization(organization, Boolean.TRUE, Boolean.FALSE);
         return Response.ok().entity(retVal).build();
     }
     
diff --git a/src/main/java/no/nibio/vips/logic/service/POIService.java b/src/main/java/no/nibio/vips/logic/service/POIService.java
index 4ca5a1f5..b0104d40 100644
--- a/src/main/java/no/nibio/vips/logic/service/POIService.java
+++ b/src/main/java/no/nibio/vips/logic/service/POIService.java
@@ -18,40 +18,46 @@
 package no.nibio.vips.logic.service;
 
 import java.io.IOException;
-import java.text.SimpleDateFormat;
-import java.util.*;
-
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.ws.rs.*;
-import jakarta.ws.rs.core.Context;
-import jakarta.ws.rs.core.HttpHeaders;
-import jakarta.ws.rs.core.MediaType;
-import jakarta.ws.rs.core.Response;
-import jakarta.ws.rs.core.Response.Status;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import no.nibio.vips.logic.controller.session.PointOfInterestBean;
-import no.nibio.vips.logic.entity.helpers.PointOfInterestFactory;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.locationtech.jts.geom.Coordinate;
 import org.locationtech.jts.geom.Point;
-
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.webcohesion.enunciate.metadata.Facet;
 import com.webcohesion.enunciate.metadata.rs.TypeHint;
-
-import java.util.stream.Collectors;
-
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 import no.nibio.vips.gis.GISUtil;
+import no.nibio.vips.logic.controller.session.PointOfInterestBean;
+import no.nibio.vips.logic.controller.session.SessionControllerGetter;
 import no.nibio.vips.logic.entity.Country;
 import no.nibio.vips.logic.entity.Organization;
 import no.nibio.vips.logic.entity.PointOfInterest;
 import no.nibio.vips.logic.entity.PointOfInterestWeatherStation;
 import no.nibio.vips.logic.entity.VipsLogicUser;
-import no.nibio.vips.logic.controller.session.SessionControllerGetter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import no.nibio.vips.logic.entity.helpers.PointOfInterestFactory;
 
 /**
  * @copyright 2022 <a href="http://www.nibio.no/">NIBIO</a>
@@ -78,7 +84,7 @@ public class POIService {
     @TypeHint(PointOfInterestWeatherStation[].class)
     public Response getPoisForOrganization(@PathParam("organizationId") Integer organizationId) {
         Organization organization = SessionControllerGetter.getUserBean().getOrganization(organizationId);
-        List<PointOfInterestWeatherStation> retVal = SessionControllerGetter.getPointOfInterestBean().getWeatherstationsForOrganization(organization, Boolean.TRUE);
+        List<PointOfInterestWeatherStation> retVal = SessionControllerGetter.getPointOfInterestBean().getWeatherstationsForOrganization(organization, Boolean.TRUE, Boolean.FALSE);
         return Response.ok().entity(retVal).build();
     }
 
-- 
GitLab