From 8f1fd0066a7ca5bf20aa71b4690fa5752076c85e Mon Sep 17 00:00:00 2001
From: Tor-Einar Skog <tor-einar.skog@nibio.no>
Date: Tue, 27 Aug 2024 14:43:48 +0200
Subject: [PATCH] Add selection of grid weather datasource to organization form

---
 .../servlet/OrganizationController.java       | 10 ++++++++++
 .../session/PointOfInterestBean.java          |  9 +++++++++
 .../entity/WeatherStationDataSource.java      | 11 ++++++++++
 .../V20__Add_Datasource_Property_IsGrid.sql   |  3 +++
 .../vips/logic/i18n/vipslogictexts.properties |  1 +
 .../logic/i18n/vipslogictexts_bs.properties   |  1 +
 .../logic/i18n/vipslogictexts_hr.properties   |  1 +
 .../logic/i18n/vipslogictexts_nb.properties   |  1 +
 .../logic/i18n/vipslogictexts_sr.properties   |  1 +
 .../i18n/vipslogictexts_zh_CN.properties      |  1 +
 .../formdefinitions/organizationForm.json     |  6 ++++++
 .../webapp/templates/organizationForm.ftl     | 20 +++++++++++++++----
 12 files changed, 61 insertions(+), 4 deletions(-)
 create mode 100644 src/main/resources/db/migration/V20__Add_Datasource_Property_IsGrid.sql

diff --git a/src/main/java/no/nibio/vips/logic/controller/servlet/OrganizationController.java b/src/main/java/no/nibio/vips/logic/controller/servlet/OrganizationController.java
index b10c713a..ed2e9fd7 100644
--- a/src/main/java/no/nibio/vips/logic/controller/servlet/OrganizationController.java
+++ b/src/main/java/no/nibio/vips/logic/controller/servlet/OrganizationController.java
@@ -29,6 +29,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import no.nibio.vips.gis.GISUtil;
 import no.nibio.vips.gis.LonLatStringFormatException;
+import no.nibio.vips.logic.controller.session.PointOfInterestBean;
 import no.nibio.vips.logic.controller.session.UserBean;
 import no.nibio.vips.logic.entity.Organization;
 import no.nibio.vips.logic.entity.VipsLogicUser;
@@ -46,6 +47,9 @@ public class OrganizationController extends HttpServlet {
     
     @EJB
     UserBean userBean;
+
+    @EJB
+    PointOfInterestBean poiBean;
    
     /** 
      * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
@@ -101,6 +105,7 @@ public class OrganizationController extends HttpServlet {
             request.setAttribute("countries", userBean.getCountries());
             request.setAttribute("timeZones", TimeZone.getAvailableIDs());
             request.setAttribute("organization", organization);
+            request.setAttribute("gridWeatherDataSources", poiBean.getGridWeatherStationDataSources());
             request.getRequestDispatcher("/organizationForm.ftl").forward(request, response);
         }
         else if(action.equals("organizationFormSubmit"))
@@ -142,6 +147,11 @@ public class OrganizationController extends HttpServlet {
                                     : new GISUtil().getJtsPointFromString(formValidation.getFormField("defaultMapCenter").getWebValue())
                     );
                     
+                    organization.setDefaultGridWeatherStationDataSource(
+                        formValidation.getFormField("defaultGridWeatherStationDataSourceId").getValueAsInteger() < 0 ?
+                        null
+                        : poiBean.getWeatherStationDataSource(formValidation.getFormField("defaultGridWeatherStationDataSourceId").getValueAsInteger())
+                    );
                     organization = userBean.storeOrganization(organization);
                     
                     response.sendRedirect(
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 7c82e925..b7f95ffa 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
@@ -263,10 +263,19 @@ 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();
+    }
+
     public PointOfInterestWeatherStation storeWeatherStation(PointOfInterestWeatherStation weatherStation) {
         weatherStation = em.merge(weatherStation);
         return weatherStation;
diff --git a/src/main/java/no/nibio/vips/logic/entity/WeatherStationDataSource.java b/src/main/java/no/nibio/vips/logic/entity/WeatherStationDataSource.java
index 9fe247f2..de26e921 100755
--- a/src/main/java/no/nibio/vips/logic/entity/WeatherStationDataSource.java
+++ b/src/main/java/no/nibio/vips/logic/entity/WeatherStationDataSource.java
@@ -40,6 +40,7 @@ import javax.xml.bind.annotation.XmlRootElement;
 @XmlRootElement
 @NamedQueries({
     @NamedQuery(name = "WeatherStationDataSource.findAll", query = "SELECT w FROM WeatherStationDataSource w"),
+    @NamedQuery(name = "WeatherStationDataSource.findGridSources", query = "SELECT w FROM WeatherStationDataSource w WHERE w.isGrid IS TRUE"),
     @NamedQuery(name = "WeatherStationDataSource.findByWeatherStationDataSourceId", query = "SELECT w FROM WeatherStationDataSource w WHERE w.weatherStationDataSourceId = :weatherStationDataSourceId"),
     @NamedQuery(name = "WeatherStationDataSource.findByName", query = "SELECT w FROM WeatherStationDataSource w WHERE w.name = :name"),
     @NamedQuery(name = "WeatherStationDataSource.findByDefaultDescription", query = "SELECT w FROM WeatherStationDataSource w WHERE w.defaultDescription = :defaultDescription"),
@@ -68,6 +69,16 @@ public class WeatherStationDataSource implements Serializable {
     @Size(max = 1024)
     @Column(name = "info_uri_expression")
     private String infoUriExpression;
+    @Column(name = "is_grid")
+    private Boolean isGrid;
+
+    public Boolean getIsGrid() {
+        return isGrid;
+    }
+
+    public void setIsGrid(Boolean isGrid) {
+        this.isGrid = isGrid;
+    }
 
     public WeatherStationDataSource() {
     }
diff --git a/src/main/resources/db/migration/V20__Add_Datasource_Property_IsGrid.sql b/src/main/resources/db/migration/V20__Add_Datasource_Property_IsGrid.sql
new file mode 100644
index 00000000..468128cb
--- /dev/null
+++ b/src/main/resources/db/migration/V20__Add_Datasource_Property_IsGrid.sql
@@ -0,0 +1,3 @@
+-- Adding this property when adding support for gridded weather datasources in VIPS
+ALTER TABLE weather_station_data_source
+ADD COLUMN is_grid BOOLEAN DEFAULT FALSE;
\ No newline at end of file
diff --git a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties
index ea2b3d71..849d6e2f 100755
--- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties
+++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties
@@ -1054,3 +1054,4 @@ thresholdDSVMax=DSV threshold for high infection risk
 thresholdDSVTempMin=Minimum temperature for DSV calculation
 useGridWeatherData=Use grid weather data
 doNotUse=Do not use
+defaultGridWeatherStationDataSource=Gridded weather data source
diff --git a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_bs.properties b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_bs.properties
index b632979d..3fb8bdfe 100755
--- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_bs.properties
+++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_bs.properties
@@ -1048,3 +1048,4 @@ thresholdDSVMax=DSV threshold for high infection risk
 thresholdDSVTempMin=Minimum temperature for DSV calculation
 useGridWeatherData=Use grid weather data
 doNotUse=Do not use
+defaultGridWeatherStationDataSource=Gridded weather data source
diff --git a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_hr.properties b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_hr.properties
index 286433a3..3f488790 100755
--- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_hr.properties
+++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_hr.properties
@@ -1046,3 +1046,4 @@ thresholdDSVMax=DSV threshold for high infection risk
 thresholdDSVTempMin=Minimum temperature for DSV calculation
 useGridWeatherData=Use grid weather data
 doNotUse=Do not use
+defaultGridWeatherStationDataSource=Gridded weather data source
diff --git a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_nb.properties b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_nb.properties
index 8629648d..0a3f9103 100755
--- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_nb.properties
+++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_nb.properties
@@ -1054,3 +1054,4 @@ thresholdDSVMax=DSV-terskel for h\u00f8y infeksjonsrisiko
 thresholdDSVTempMin=Minimumstemperatur for beregning av DSV
 useGridWeatherData=Bruk v\u00e6rdata fra rutenett
 doNotUse=Ikke bruk
+defaultGridWeatherStationDataSource=GRID-basert v\u00e6rdatakilde
diff --git a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_sr.properties b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_sr.properties
index 044f7b23..be4ee828 100755
--- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_sr.properties
+++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_sr.properties
@@ -1048,3 +1048,4 @@ thresholdDSVMax=DSV threshold for high infection risk
 thresholdDSVTempMin=Minimum temperature for DSV calculation
 useGridWeatherData=Use grid weather data
 doNotUse=Do not use
+defaultGridWeatherStationDataSource=Gridded weather data source
diff --git a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_zh_CN.properties b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_zh_CN.properties
index 66a5fd1c..62560ca5 100755
--- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_zh_CN.properties
+++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_zh_CN.properties
@@ -1042,3 +1042,4 @@ thresholdDSVMax=DSV threshold for high infection risk
 thresholdDSVTempMin=Minimum temperature for DSV calculation
 useGridWeatherData=Use grid weather data
 doNotUse=Do not use
+defaultGridWeatherStationDataSource=Gridded weather data source
diff --git a/src/main/webapp/formdefinitions/organizationForm.json b/src/main/webapp/formdefinitions/organizationForm.json
index acc63d9e..4ff9c999 100644
--- a/src/main/webapp/formdefinitions/organizationForm.json
+++ b/src/main/webapp/formdefinitions/organizationForm.json
@@ -95,6 +95,12 @@
             "name" : "defaultMapCenter",
             "dataType" : "STRING",
             "required" : false
+        },
+        {
+            "name": "defaultGridWeatherStationDataSourceId",
+            "dataType": "INTEGER",
+            "fieldType": "SELECT_SINGLE",
+            "required": false
         }
         
     ]
diff --git a/src/main/webapp/templates/organizationForm.ftl b/src/main/webapp/templates/organizationForm.ftl
index 50ac1afc..cb907e21 100644
--- a/src/main/webapp/templates/organizationForm.ftl
+++ b/src/main/webapp/templates/organizationForm.ftl
@@ -119,7 +119,7 @@
 			    <input type="text" class="form-control" name="vipswebUrl" placeholder="${i18nBundle.vipswebUrl}" value="${(organization.vipswebUrl)!""}" onblur="validateField(this); "/>
 			    <span class="help-block" id="${formId}_vipswebUrl_validation"></span>
 			  </div>
-                          <div class="form-group">
+                <div class="form-group">
 			    <label for="archiveUserId">${i18nBundle.archiveUserId}</label>
 			    <select class="form-control" name="archiveUserId" onblur="validateField(this);">
 			    	<option value="-1">${i18nBundle.pleaseSelect} ${i18nBundle.archiveUserId?lower_case}
@@ -131,21 +131,33 @@
 			     </select>
 			     <span class="help-block" id="${formId}_archiveUserId_validation"></span>
 			  </div>
-                          <div class="form-group">
+                <div class="form-group">
 			    <label for="defaultVipsCoreUserId">${i18nBundle.defaultVipsCoreUserId}</label>
 			    <input type="number" class="form-control" name="defaultVipsCoreUserId" placeholder="${i18nBundle.defaultVipsCoreUserId}" value="${(organization.defaultVipsCoreUserId)!""}" onblur="validateField(this); "/>
 			    <span class="help-block" id="${formId}_defaultVipsCoreUserId_validation"></span>
 			  </div>
-                           <div class="form-group">
+                <div class="form-group">
 			    <label for="defaultMapZoom">${i18nBundle.defaultMapZoom}</label>
 			    <input type="number" class="form-control" name="defaultMapZoom" placeholder="${i18nBundle.defaultMapZoom}" value="${(organization.defaultMapZoom)!""}" onblur="validateField(this); "/>
 			    <span class="help-block" id="${formId}_defaultMapZoom_validation"></span>
 			  </div>
-                          <div class="form-group">
+                <div class="form-group">
 			    <label for="defaultMapCenter">${i18nBundle.defaultMapCenter} (WGS84 longitude,latitude)</label>
 			    <input type="text" class="form-control" name="defaultMapCenter" placeholder="${i18nBundle.defaultMapCenter}" value="${(defaultMapCenterLon?c)!""},${(defaultMapCenterLat?c)!""}" onblur="validateField(this); "/>
 			    <span class="help-block" id="${formId}_defaultMapCenter_validation"></span>
 			  </div>
+			  <div class="form-group">
+			    <label for="defaultGridWeatherStationDataSourceId">${i18nBundle.defaultGridWeatherStationDataSource}</label>
+			    <select class="form-control" name="defaultGridWeatherStationDataSourceId" onblur="validateField(this);">
+			    	<option value="-1">${i18nBundle.pleaseSelect} ${i18nBundle.defaultGridWeatherStationDataSource?lower_case}
+				<#list gridWeatherDataSources as dSource>
+					<option value="${dSource.weatherStationDataSourceId}"
+						<#if organization.defaultGridWeatherStationDataSource?has_content && organization.defaultGridWeatherStationDataSource.weatherStationDataSourceId == dSource.weatherStationDataSourceId>selected="selected"</#if>
+					>${dSource.name}</option>
+				</#list>
+			     </select>
+			     <span class="help-block" id="${formId}_defaultGridWeatherStationDataSourceId_validation"></span>
+			  </div>
 			  <button type="submit" class="btn btn-default">${i18nBundle.submit}</button>
 			  <#if organization.organizationId?has_content>
 			  <button type="button" class="btn btn-danger" onclick="if(confirm('${i18nBundle.confirmDelete}')){alert('Sorry, but this functionality has not yet been implemented');}">${i18nBundle.delete}</button>
-- 
GitLab