Skip to content
Snippets Groups Projects
Commit 77423bb7 authored by Tor-Einar Skog's avatar Tor-Einar Skog
Browse files

Merge branch 'develop' into 'Observation'

# Conflicts:
#   src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties
#   src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_bs.properties
#   src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_hr.properties
#   src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_nb.properties
#   src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_sr.properties
#   src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_zh_CN.properties
parents 4afacefd a032cf5f
Branches
Tags
2 merge requests!22Develop,!19Observation
Showing
with 1053 additions and 10 deletions
#!groovy
node {
try {
stage 'Checkout'
checkout scm
stage 'Test'
sh """
mvn test
"""
stage 'Build'
}
catch (err) {
throw err
}
}
......@@ -186,6 +186,12 @@
<version>2.9.8</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.9.8</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.locationtech.jts</groupId>
<artifactId>jts-core</artifactId>
......
......@@ -55,6 +55,8 @@ public class VIPSLogicApplication extends Application
resources.add(no.nibio.vips.logic.modules.applefruitmoth.AppleFruitMothService.class);
resources.add(no.nibio.vips.logic.service.ObservationService.class);
resources.add(no.nibio.vips.logic.service.ModelFormService.class);
resources.add(no.nibio.vips.logic.service.GrowthStageService.class);
resources.add(no.nibio.vips.logic.service.JacksonConfig.class);
//resources.add(no.nibio.vips.logic.service.JSONBConfig.class);
//resources.add(no.nibio.vips.coremanager.service.ManagerResourceImpl.class);
......@@ -71,6 +73,7 @@ public class VIPSLogicApplication extends Application
resources.add(no.nibio.vips.logic.modules.barleynetblotch.BarleyNetBlotchModelService.class);
resources.add(no.nibio.vips.logic.modules.roughage.RoughageService.class);
resources.add(no.nibio.vips.logic.modules.wheatleafblotch.WheatLeafBlotchModelService.class);
resources.add(no.nibio.vips.logic.service.GrowthStageService.class);
resources.add(no.nibio.vips.logic.service.JSONBConfig.class);
resources.add(no.nibio.vips.logic.service.JacksonConfig.class);
resources.add(no.nibio.vips.logic.service.LogicService.class);
......
......@@ -563,7 +563,7 @@ public class ForecastBean {
* @param camelCaseName
* @return MODELID_CAMEL_CASE_NAME
*/
private 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})"))
......@@ -573,7 +573,7 @@ public class ForecastBean {
return deCamelizedFieldName.toString();
}
public List<ForecastModelConfiguration> getForecastModelConfigurations(Long forecastConfigurationId)
{
......@@ -1203,4 +1203,17 @@ public class ForecastBean {
.setParameter("userId", user.getUserId())
.executeUpdate();
}
/**
*
* @param modelId
* @param year
* @return
*/
public List<ForecastConfiguration> getForecastConfigurationsForModel(String modelId, Integer year) {
return em.createNamedQuery("ForecastConfiguration.findByModelIdAndYear")
.setParameter("modelId", modelId)
.setParameter("year", year)
.getResultList();
}
}
......@@ -292,6 +292,10 @@ public class ObservationBean {
public void deleteObservation(Integer observationId) {
Observation observation = em.find(Observation.class, observationId);
// Delete all current group memberships
em.createNativeQuery("DELETE FROM public.organization_group_observation WHERE observation_id=:observationId")
.setParameter("observationId", observation.getObservationId())
.executeUpdate();
em.remove(observation);
}
......
......@@ -46,7 +46,7 @@ import no.nibio.vips.logic.entity.OrganismLocalePK;
import no.nibio.vips.logic.util.HierarchyCategoryLocaleNames;
/**
* @copyright 2014 <a href="http://www.nibio.no/">NIBIO</a>
* @copyright 2014-2020 <a href="http://www.nibio.no/">NIBIO</a>
* @author Tor-Einar Skog <tor-einar.skog@nibio.no>
*/
@Stateless
......@@ -481,4 +481,11 @@ public class OrganismBean {
public List<Organism> findOrganismsByLatinNames(List<String> latinNames) {
return em.createNamedQuery("Organism.findByLatinNames").setParameter("latinNames", latinNames).getResultList();
}
public List<Organism> findOrganismsByLocalNames(List<String> localNames, String locale) {
return em.createNamedQuery("Organism.findByLocalNames")
.setParameter("localNames", localNames)
.setParameter("locale", locale)
.getResultList();
}
}
......@@ -483,7 +483,96 @@ public class PointOfInterestBean {
.setParameter("name", dataSourceName)
.getSingleResult();
}
/**
* Utility method to find the nearest weather station
* @param location
* @return
*/
public PointOfInterestWeatherStation findClosestWeatherStation(com.vividsolutions.jts.geom.Coordinate location)
{
return this.findClosestWeatherStation(location.x, location.y);
}
public PointOfInterestWeatherStation findClosestWeatherStation(Double longitude, Double latitude)
{
List<PointOfInterestWeatherStation> weatherStations = em.createNamedQuery("PointOfInterestWeatherStation.findAll", PointOfInterestWeatherStation.class)
.getResultList();
return this.findClosestWeatherStation(longitude, latitude, weatherStations);
}
/**
* Utility method to find the nearest weather station
* @param location
* @return
*/
public PointOfInterestWeatherStation findClosestWeatherStation(com.vividsolutions.jts.geom.Coordinate location, List<PointOfInterestWeatherStation> weatherStations)
{
return this.findClosestWeatherStation(location.x, location.y, weatherStations);
}
/**
* Utility method to find the nearest weather station
* @param longitude
* @param latitude
* @return
*/
public PointOfInterestWeatherStation findClosestWeatherStation(Double longitude, Double latitude, List<PointOfInterestWeatherStation> weatherStations)
{
PointOfInterestWeatherStation retVal = null;
Double minimumDistance = null; // km
for(PointOfInterestWeatherStation ws:weatherStations)
{
Double distance = this.calculateDistance(latitude, longitude, ws.getLatitude(), ws.getLongitude());
if(minimumDistance == null || minimumDistance >= distance)
{
minimumDistance = distance;
retVal = ws;
}
}
return retVal;
}
/**
* Based on <a href="http://www.movable-type.co.uk/scripts/latlong.html">this</a>. Explanation:
* <pre>
* This uses the "haversine" formula to calculate the great-circle distance between two points ? that is, the shortest distance over the earth?s surface ? giving an ?as-the-crow-flies? distance between the points (ignoring any hills, of course!).
Haversine formula:
a = sin²(∆lat/2) + cos(lat1).cos(lat2).sin²(∆long/2)
c = 2 * atan2(√a,√(1-a))
d = R*c
where R is earth's radius (mean radius = 6,371km);
Note that angles need to be in radians to pass to trig functions!
* </pre>
* @param lat1 WGS84 latitude of point 1
* @param long1 WGS84 longitude of point 1
* @param lat2 WGS84 latitude of point 2
* @param long2 WGS84 longitude of point 2
* @return distance in km
*/
public Double calculateDistance(Double lat1, Double long1, Double lat2, Double long2)
{
Integer R = 6371; // km
Double dLat = Math.toRadians(lat2-lat1);
Double dLon = Math.toRadians(long2-long1);
lat1 = Math.toRadians(lat1);
lat2 = Math.toRadians(lat2);
Double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
Double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
Double d = R * c;
return d;
}
}
......@@ -82,7 +82,8 @@ import org.hibernate.annotations.TypeDefs;
@NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserIds", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId IN (:vipsLogicUserIds) AND f.isPrivate = FALSE"),
@NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserIdsAndModelIds", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId IN (:vipsLogicUserIds) AND f.modelId IN (:modelIds) AND f.isPrivate = FALSE"),
@NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserIdsAndModelIdsAndDate", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId IN (:vipsLogicUserIds) AND f.modelId IN (:modelIds) AND f.dateStart <= :to AND f.dateEnd >= :from AND f.isPrivate = FALSE"),
@NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserIdsAndDate", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId IN (:vipsLogicUserIds) AND f.dateStart <= :to AND f.dateEnd >= :from AND f.isPrivate = FALSE")
@NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserIdsAndDate", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId IN (:vipsLogicUserIds) AND f.dateStart <= :to AND f.dateEnd >= :from AND f.isPrivate = FALSE"),
@NamedQuery(name = "ForecastConfiguration.findByModelIdAndYear", query = "SELECT f FROM ForecastConfiguration f WHERE f.modelId = :modelId AND YEAR(f.dateStart) <= :year AND YEAR(f.dateEnd) >= :year AND f.isPrivate = FALSE")
})
public class ForecastConfiguration implements Serializable, Comparable {
@OneToMany(cascade = CascadeType.ALL, mappedBy = "forecastConfiguration", fetch = FetchType.EAGER)
......
......@@ -42,7 +42,7 @@ import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
/**
* @copyright 2013-2014 <a href="http://www.nibio.no/">NIBIO</a>
* @copyright 2013-2020 <a href="http://www.nibio.no/">NIBIO</a>
* @author Tor-Einar Skog <tor-einar.skog@nibio.no>
*/
@Entity
......@@ -57,6 +57,7 @@ import javax.xml.bind.annotation.XmlRootElement;
@NamedQuery(name = "Organism.findByParentOrganismId", query = "SELECT o FROM Organism o WHERE o.parentOrganismId = :parentOrganismId"),
@NamedQuery(name = "Organism.findByLatinName", query = "SELECT o FROM Organism o WHERE o.latinName = :latinName"),
@NamedQuery(name = "Organism.findByLatinNames", query = "SELECT o FROM Organism o WHERE o.latinName IN :latinNames"),
@NamedQuery(name = "Organism.findByLocalNames", query = "SELECT o FROM Organism o WHERE o.organismId IN (SELECT ol.organismId FROM OrganismLocale ol WHERE ol.localName IN(:localNames) AND ol.organismLocalePK.locale = :locale)"),
@NamedQuery(name = "Organism.findByTradeName", query = "SELECT o FROM Organism o WHERE o.tradeName = :tradeName"),
@NamedQuery(name = "Organism.findByLogicallyDeleted", query = "SELECT o FROM Organism o WHERE o.logicallyDeleted = :logicallyDeleted")})
public class Organism implements Serializable {
......
......@@ -30,7 +30,7 @@ import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
/**
* @copyright 2013-2014 <a href="http://www.nibio.no/">NIBIO</a>
* @copyright 2013-2020 <a href="http://www.nibio.no/">NIBIO</a>
* @author Tor-Einar Skog <tor-einar.skog@nibio.no>
*/
@Entity
......@@ -40,7 +40,8 @@ import javax.xml.bind.annotation.XmlRootElement;
@NamedQuery(name = "OrganismLocale.findAll", query = "SELECT o FROM OrganismLocale o"),
@NamedQuery(name = "OrganismLocale.findByOrganismId", query = "SELECT o FROM OrganismLocale o WHERE o.organismLocalePK.organismId = :organismId"),
@NamedQuery(name = "OrganismLocale.findByLocale", query = "SELECT o FROM OrganismLocale o WHERE o.organismLocalePK.locale = :locale"),
@NamedQuery(name = "OrganismLocale.findByLocalName", query = "SELECT o FROM OrganismLocale o WHERE o.localName = :localName")})
@NamedQuery(name = "OrganismLocale.findByLocalName", query = "SELECT o FROM OrganismLocale o WHERE o.localName = :localName")//,
})
public class OrganismLocale implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
......
/*
* Copyright (c) 2020 NIBIO <http://www.nibio.no/>.
*
* This file is part of VIPSLogic.
* VIPSLogic is free software: you can redistribute it and/or modify
* it under the terms of the NIBIO Open Source License as published by
* NIBIO, either version 1 of the License, or (at your option) any
* later version.
*
* VIPSLogic 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
* NIBIO Open Source License for more details.
*
* You should have received a copy of the NIBIO Open Source License
* along with VIPSLogic. If not, see <http://www.nibio.no/licenses/>.
*
*/
package no.nibio.vips.logic.modules.wheatleafblotch;
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.xml.bind.annotation.XmlRootElement;
/**
* @copyright 2020 <a href="http://www.nibio.no/">NIBIO</a>
* @author Tor-Einar Skog <tor-einar.skog@nibio.no>
*/
@Entity
@Table(name = "growth_stage_location_date", schema = "wheatleafb")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "GrowthStageLocationDate.findAll", query = "SELECT g FROM GrowthStageLocationDate g"),
@NamedQuery(name = "GrowthStageLocationDate.findByPointOfInterestId", query = "SELECT g FROM GrowthStageLocationDate g WHERE g.growthStageLocationDatePK.pointOfInterestId = :pointOfInterestId"),
@NamedQuery(name = "GrowthStageLocationDate.findByCropOrganismId", query = "SELECT g FROM GrowthStageLocationDate g WHERE g.growthStageLocationDatePK.cropOrganismId = :cropOrganismId"),
@NamedQuery(name = "GrowthStageLocationDate.findByCropOrganismIdAndPointOfInterestId", query = "SELECT g FROM GrowthStageLocationDate g WHERE g.growthStageLocationDatePK.cropOrganismId = :cropOrganismId AND g.growthStageLocationDatePK.pointOfInterestId = :pointOfInterestId")
})
public class GrowthStageLocationDate implements Serializable, Comparable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private GrowthStageLocationDatePK growthStageLocationDatePK;
@Column(name = "day_number")
private Integer dayNumber;
public GrowthStageLocationDate() {
}
public GrowthStageLocationDate(GrowthStageLocationDatePK growthStateLocationPK) {
this.growthStageLocationDatePK = growthStateLocationPK;
}
@Override
public int hashCode() {
int hash = 0;
hash += (getGrowthStageLocationDatePK() != null ? getGrowthStageLocationDatePK().hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof GrowthStageLocationDate)) {
return false;
}
GrowthStageLocationDate other = (GrowthStageLocationDate) object;
if ((this.getGrowthStageLocationDatePK() == null && other.getGrowthStageLocationDatePK() != null) || (this.getGrowthStageLocationDatePK() != null && !this.growthStageLocationDatePK.equals(other.growthStageLocationDatePK))) {
return false;
}
return true;
}
@Override
public String toString() {
return "no.nibio.vips.logic.modules.wheatleafblotch.GrowthStageLocationDate[ growthStageLocationDatePK=" + getGrowthStageLocationDatePK() + " ]";
}
/**
* @return the dayNumber
*/
public Integer getDayNumber() {
return dayNumber;
}
/**
* @param dayNumber the dayNumber to set
*/
public void setDayNumber(Integer dayNumber) {
this.dayNumber = dayNumber;
}
@Override
public int compareTo(Object t) {
return this.getGrowthStageLocationDatePK().getGrowthStage().compareTo(((GrowthStageLocationDate) t).getGrowthStageLocationDatePK().getGrowthStage()
);
}
/**
* @return the growthStageLocationDatePK
*/
public GrowthStageLocationDatePK getGrowthStageLocationDatePK() {
return growthStageLocationDatePK;
}
/**
* @param growthStageLocationDatePK the growthStageLocationDatePK to set
*/
public void setGrowthStageLocationDatePK(GrowthStageLocationDatePK growthStageLocationDatePK) {
this.growthStageLocationDatePK = growthStageLocationDatePK;
}
}
/*
* Copyright (c) 2020 NIBIO <http://www.nibio.no/>.
*
* This file is part of VIPSLogic.
* VIPSLogic is free software: you can redistribute it and/or modify
* it under the terms of the NIBIO Open Source License as published by
* NIBIO, either version 1 of the License, or (at your option) any
* later version.
*
* VIPSLogic 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
* NIBIO Open Source License for more details.
*
* You should have received a copy of the NIBIO Open Source License
* along with VIPSLogic. If not, see <http://www.nibio.no/licenses/>.
*
*/
package no.nibio.vips.logic.modules.wheatleafblotch;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.validation.constraints.NotNull;
import no.nibio.vips.logic.entity.Organism;
import no.nibio.vips.logic.entity.PointOfInterest;
/**
* @copyright 2020 <a href="http://www.nibio.no/">NIBIO</a>
* @author Tor-Einar Skog <tor-einar.skog@nibio.no>
*/
@Embeddable
public class GrowthStageLocationDatePK implements Serializable {
@Basic(optional = false)
@NotNull
@JoinColumn(name = "crop_organism_id", referencedColumnName = "organism_id")
@ManyToOne
private Organism cropOrganismId;
@Basic(optional = false)
@NotNull
@JoinColumn(name = "point_of_interest_id", referencedColumnName = "point_of_interest_id")
@ManyToOne
private PointOfInterest pointOfInterestId;
@Column(name = "growth_stage")
private Integer growthStage;
public GrowthStageLocationDatePK() {
}
public GrowthStageLocationDatePK(Organism organism, PointOfInterest pointOfInterestId) {
this.cropOrganismId = organism;
this.pointOfInterestId = pointOfInterestId;
}
public Organism getCropOrganismId() {
return cropOrganismId;
}
public void setCropOrganismId(Organism cropOrganismId) {
this.cropOrganismId = cropOrganismId;
}
public PointOfInterest getPointOfInterestId() {
return pointOfInterestId;
}
public void setPointOfInterestId(PointOfInterest pointOfInterestId) {
this.pointOfInterestId = pointOfInterestId;
}
public Integer getGrowthStage() {
return growthStage;
}
public void setGrowthStage(Integer growthStage) {
this.growthStage = growthStage;
}
@Override
public int hashCode() {
int hash = 0;
hash += (int) cropOrganismId.getOrganismId();
hash += (int) pointOfInterestId.getPointOfInterestId();
hash += (int) growthStage;
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof GrowthStageLocationDatePK)) {
return false;
}
GrowthStageLocationDatePK other = (GrowthStageLocationDatePK) object;
if (this.cropOrganismId != other.cropOrganismId) {
return false;
}
if (this.pointOfInterestId != other.pointOfInterestId) {
return false;
}
if(! this.growthStage.equals(other.growthStage)){
return false;
}
return true;
}
@Override
public String toString() {
return "no.nibio.vips.logic.modules.wheatleafblotch.YieldLossPK[ organism=" + cropOrganismId + ", pointOfInterestId=" + pointOfInterestId + " ]";
}
}
......@@ -143,6 +143,46 @@ public class WheatLeafBlotchModelService {
}
}
/**
* Returns the yield loss from Septoria in wheat(?)
* @param organizationId
* @param season
* @return
*/
@GET
@Path("yieldloss/septoria/{organizationId}/{season}")
@Produces("application/json;charset=UTF-8")
public Response getYieldLoss(
@PathParam("organizationId") Integer organizationId,
@PathParam("season") Integer season
)
{
List<YieldLoss> retVal;
if(organizationId <= 0)
{
retVal = em.createNamedQuery("YieldLoss.findBySeason")
.setParameter("season", season)
.getResultList();
}
else
{
retVal = em.createNativeQuery("SELECT * FROM wheatleafb.yield_loss \n" +
"WHERE season = :season\n" +
"AND point_of_interest_id IN (\n" +
" SELECT point_of_interest_id FROM point_of_interest\n" +
" WHERE user_id IN (SELECT user_id FROM vips_logic_user WHERE organization_id = :organizationId" +
" )\n" +
")"
,
YieldLoss.class
)
.setParameter("organizationId", organizationId)
.setParameter("season", season)
.getResultList();
}
return Response.ok().entity(retVal).build();
}
@GET
@Path("runmodel/{organizationId}")
@Produces("application/json;charset=UTF-8")
......
/*
* Copyright (c) 2019 NIBIO <http://www.nibio.no/>.
*
* This file is part of VIPSLogic.
* VIPSLogic is free software: you can redistribute it and/or modify
* it under the terms of the NIBIO Open Source License as published by
* NIBIO, either version 1 of the License, or (at your option) any
* later version.
*
* VIPSLogic 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
* NIBIO Open Source License for more details.
*
* You should have received a copy of the NIBIO Open Source License
* along with VIPSLogic. If not, see <http://www.nibio.no/licenses/>.
*
*/
package no.nibio.vips.logic.modules.wheatleafblotch;
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.xml.bind.annotation.XmlRootElement;
import no.nibio.vips.logic.entity.PointOfInterest;
/**
* @copyright 2019 <a href="http://www.nibio.no/">NIBIO</a>
* @author Tor-Einar Skog <tor-einar.skog@nibio.no>
*/
@Entity
@Table(name = "yield_loss", schema = "wheatleafb")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "YieldLoss.findAll", query = "SELECT y FROM YieldLoss y"),
@NamedQuery(name = "YieldLoss.findBySeason", query = "SELECT y FROM YieldLoss y WHERE y.yieldLossPK.season = :season"),
@NamedQuery(name = "YieldLoss.findByPointOfInterestId", query = "SELECT y FROM YieldLoss y WHERE y.yieldLossPK.pointOfInterestId = :pointOfInterestId"),
@NamedQuery(name = "YieldLoss.findByYieldLoss", query = "SELECT y FROM YieldLoss y WHERE y.yieldLoss = :yieldLoss")
})
public class YieldLoss implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
protected YieldLossPK yieldLossPK;
@Column(name = "yield_loss")
private Double yieldLoss;
public YieldLoss() {
}
public YieldLoss(YieldLossPK yieldLossPK) {
this.yieldLossPK = yieldLossPK;
}
public YieldLoss(int season, PointOfInterest pointOfInterestId) {
this.yieldLossPK = new YieldLossPK(season, pointOfInterestId);
}
public YieldLossPK getYieldLossPK() {
return yieldLossPK;
}
public void setYieldLossPK(YieldLossPK yieldLossPK) {
this.yieldLossPK = yieldLossPK;
}
public Double getYieldLoss() {
return yieldLoss;
}
public void setYieldLoss(Double yieldLoss) {
this.yieldLoss = yieldLoss;
}
@Override
public int hashCode() {
int hash = 0;
hash += (yieldLossPK != null ? yieldLossPK.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof YieldLoss)) {
return false;
}
YieldLoss other = (YieldLoss) object;
if ((this.yieldLossPK == null && other.yieldLossPK != null) || (this.yieldLossPK != null && !this.yieldLossPK.equals(other.yieldLossPK))) {
return false;
}
return true;
}
@Override
public String toString() {
return "no.nibio.vips.logic.modules.wheatleafblotch.YieldLoss[ yieldLossPK=" + yieldLossPK + " ]";
}
}
/*
* Copyright (c) 2019 NIBIO <http://www.nibio.no/>.
*
* This file is part of VIPSLogic.
* VIPSLogic is free software: you can redistribute it and/or modify
* it under the terms of the NIBIO Open Source License as published by
* NIBIO, either version 1 of the License, or (at your option) any
* later version.
*
* VIPSLogic 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
* NIBIO Open Source License for more details.
*
* You should have received a copy of the NIBIO Open Source License
* along with VIPSLogic. If not, see <http://www.nibio.no/licenses/>.
*
*/
package no.nibio.vips.logic.modules.wheatleafblotch;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.validation.constraints.NotNull;
import no.nibio.vips.logic.entity.PointOfInterest;
/**
* @copyright 2019 <a href="http://www.nibio.no/">NIBIO</a>
* @author Tor-Einar Skog <tor-einar.skog@nibio.no>
*/
@Embeddable
public class YieldLossPK implements Serializable {
@Basic(optional = false)
@NotNull
@Column(name = "season")
private int season;
@Basic(optional = false)
@NotNull
@JoinColumn(name = "point_of_interest_id", referencedColumnName = "point_of_interest_id")
@ManyToOne
private PointOfInterest pointOfInterestId;
public YieldLossPK() {
}
public YieldLossPK(int season, PointOfInterest pointOfInterestId) {
this.season = season;
this.pointOfInterestId = pointOfInterestId;
}
public int getSeason() {
return season;
}
public void setSeason(int season) {
this.season = season;
}
public PointOfInterest getPointOfInterestId() {
return pointOfInterestId;
}
public void setPointOfInterestId(PointOfInterest pointOfInterestId) {
this.pointOfInterestId = pointOfInterestId;
}
@Override
public int hashCode() {
int hash = 0;
hash += (int) season;
hash += (int) pointOfInterestId.getPointOfInterestId();
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof YieldLossPK)) {
return false;
}
YieldLossPK other = (YieldLossPK) object;
if (this.season != other.season) {
return false;
}
if (this.pointOfInterestId != other.pointOfInterestId) {
return false;
}
return true;
}
@Override
public String toString() {
return "no.nibio.vips.logic.modules.wheatleafblotch.YieldLossPK[ season=" + season + ", pointOfInterestId=" + pointOfInterestId + " ]";
}
}
......@@ -26,6 +26,7 @@ import java.util.Map;
import no.nibio.vips.logic.scheduling.tasks.DeleteAllExpiredUserUuidsTask;
import no.nibio.vips.logic.scheduling.tasks.RunAllForecastConfigurationsForOrganizationTask;
import no.nibio.vips.logic.scheduling.tasks.RunAllForecastConfigurationsTask;
import no.nibio.vips.logic.scheduling.tasks.RunForecastConfigurationsByIdTask;
import no.nibio.vips.logic.scheduling.tasks.RunGridModelsTask;
import no.nibio.vips.logic.scheduling.tasks.SendForecastEventNotificationsTask;
import no.nibio.vips.logic.scheduling.tasks.UpdateForecastResultCacheTableTask;
......@@ -47,8 +48,9 @@ public class VipsLogicTaskFactory {
public static final int SEND_FORECAST_EVENT_NOTIFICATIONS_TASK = 6;
public static final int RUN_ALL_FORECAST_CONFIGURATIONS_FOR_ORGANIZATION_TASK = 7;
public static final int RUN_GRID_MODELS_TASK = 8;
public static final int RUN_FORECAST_CONFIGURATIONS_BY_ID_TASK = 9;
private final static int[] ALL_TASK_IDS = {1,2,3,4,5,6,7,8};
private final static int[] ALL_TASK_IDS = {1,2,3,4,5,6,7,8,9};
private final static int[] ORGANIZATION_ADMIN_TASK_IDS = {7};
......@@ -90,6 +92,9 @@ public class VipsLogicTaskFactory {
case RUN_GRID_MODELS_TASK:
retVal = new RunGridModelsTask();
break;
case RUN_FORECAST_CONFIGURATIONS_BY_ID_TASK:
retVal = new RunForecastConfigurationsByIdTask();
break;
default:
return null;
}
......
/*
* Copyright (c) 2019 NIBIO <http://www.nibio.no/>.
*
* This file is part of VIPSLogic.
* VIPSLogic is free software: you can redistribute it and/or modify
* it under the terms of the NIBIO Open Source License as published by
* NIBIO, either version 1 of the License, or (at your option) any
* later version.
*
* VIPSLogic 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
* NIBIO Open Source License for more details.
*
* You should have received a copy of the NIBIO Open Source License
* along with VIPSLogic. If not, see <http://www.nibio.no/licenses/>.
*
*/
package no.nibio.vips.logic.scheduling.model.preprocessor;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import no.nibio.vips.entity.ModelConfiguration;
import no.nibio.vips.entity.WeatherObservation;
import no.nibio.vips.logic.entity.ForecastConfiguration;
import no.nibio.vips.logic.entity.PointOfInterestWeatherStation;
import no.nibio.vips.logic.scheduling.model.ModelRunPreprocessor;
import no.nibio.vips.logic.scheduling.model.PreprocessorException;
import no.nibio.vips.util.WeatherElements;
import no.nibio.vips.util.weather.WeatherDataSourceException;
import no.nibio.vips.util.weather.WeatherDataSourceUtil;
/**
* @copyright 2016 <a href="http://www.nibio.no/">NIBIO</a>
* @author Tor-Einar Skog <tor-einar.skog@nibio.no>
*/
public class RainyDaysModelPreprocessor extends ModelRunPreprocessor {
@Override
public ModelConfiguration getModelConfiguration(ForecastConfiguration configuration) throws PreprocessorException {
PointOfInterestWeatherStation weatherStation = (PointOfInterestWeatherStation) configuration.getWeatherStationPointOfInterestId();
// What timezone is the calculation for
TimeZone timeZone = TimeZone.getTimeZone(weatherStation.getTimeZone());
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date seasonStart = configuration.getDateStartInTimeZone();
Date seasonEnd = configuration.getDateEndInTimeZone();
try
{
if(configuration.getForecastModelConfigurationValue(this.getModelId() + "_SEASON_START") != null)
{
seasonStart = format.parse(configuration.getForecastModelConfigurationValue(this.getModelId() + "_SEASON_START"));
}
if(configuration.getForecastModelConfigurationValue(this.getModelId() + "_SEASON_END") != null)
{
seasonEnd = format.parse(configuration.getForecastModelConfigurationValue(this.getModelId() + "_SEASON_END"));
}
}
catch(ParseException ex)
{
// Keep calm and carry on?
}
ModelConfiguration retVal = new ModelConfiguration();
WeatherDataSourceUtil wdsUtil = new WeatherDataSourceUtil();
List<WeatherObservation> observations;
try {
observations = wdsUtil.getWeatherObservations(
weatherStation,
WeatherObservation.LOG_INTERVAL_ID_1D,
new String[]{
WeatherElements.PRECIPITATION
},
seasonStart,
seasonEnd);
} catch (WeatherDataSourceException ex) {
throw new PreprocessorException(ex.getMessage());
}
// If daily observations are not available, try hourly
if(observations == null || observations.isEmpty())
{
//System.out.println("No daily obs from " + weatherStation.getName() +", trying hourly");
try {
observations = wdsUtil.getWeatherObservations(
weatherStation,
WeatherObservation.LOG_INTERVAL_ID_1H,
new String[]{
WeatherElements.PRECIPITATION
},
seasonStart,
seasonEnd
);
//System.out.println("Got hourly obs from " + weatherStation.getName() +", a total of " + observations.size() + " items.");
} catch (WeatherDataSourceException ex) {
throw new PreprocessorException(ex.getMessage());
}
}
// TODO: weather data validation
retVal.setModelId(this.getModelId());
retVal.setConfigParameter("timeZone", timeZone.getID());
retVal.setConfigParameter("observations", observations);
return retVal;
}
@Override
public String getModelId() {
return "RAINYDAYSM";
}
}
......@@ -19,14 +19,20 @@
package no.nibio.vips.logic.scheduling.model.preprocessor;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import no.nibio.vips.entity.ModelConfiguration;
import no.nibio.vips.entity.WeatherObservation;
import no.nibio.vips.logic.controller.session.ForecastBean;
import no.nibio.vips.logic.entity.ForecastConfiguration;
import no.nibio.vips.logic.entity.PointOfInterestWeatherStation;
import no.nibio.vips.logic.scheduling.model.ModelRunPreprocessor;
import no.nibio.vips.logic.scheduling.model.PreprocessorException;
import no.nibio.vips.logic.util.SessionControllerGetter;
import no.nibio.vips.util.WeatherElements;
import no.nibio.vips.util.weather.WeatherDataSourceException;
import no.nibio.vips.util.weather.WeatherDataSourceUtil;
......@@ -40,12 +46,24 @@ public class SeptoriaHumidityModelPreprocessor extends ModelRunPreprocessor{
@Override
public ModelConfiguration getModelConfiguration(ForecastConfiguration configuration) throws PreprocessorException
{
ForecastBean forecastBean = SessionControllerGetter.getForecastBean();
ModelConfiguration retVal = new ModelConfiguration();
retVal.setModelId(this.getModelId());
retVal.setConfigParameter("timeZone", configuration.getTimeZone());
String[] modelConfigurationValueNames = {"dateSpraying1","dateSpraying2","dateGs31","date3rdUpperLeafEmerging",
"date2ndUpperLeafEmerging","dateUpperLeafEmerging","dateGs75","thresholdRelativeHumidity","thresholdLeafWetness",
"thresholdPrecipitation","slidingHoursPast","slidingHoursAhead","thresholdHumidPeriodHours","sprayingProtectionDays",
"leafLifeTime"};
for(String modelConfigurationValueName: modelConfigurationValueNames)
{
retVal.setConfigParameter(modelConfigurationValueName, configuration.getForecastModelConfigurationValue(forecastBean.getDeCamelizedFieldName(this.getModelId(),modelConfigurationValueName)));
}
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
format.setTimeZone(TimeZone.getTimeZone(configuration.getTimeZone()));
WeatherDataSourceUtil wdsUtil = new WeatherDataSourceUtil();
try
{
Date gs31 = format.parse((String)retVal.getConfigParameter("dateGs31"));
List<WeatherObservation> observations = wdsUtil.getWeatherObservations(
(PointOfInterestWeatherStation) configuration.getWeatherStationPointOfInterestId(),
WeatherObservation.LOG_INTERVAL_ID_1H,
......@@ -55,13 +73,13 @@ public class SeptoriaHumidityModelPreprocessor extends ModelRunPreprocessor{
WeatherElements.RELATIVE_HUMIDITY_MEAN,
WeatherElements.LEAF_WETNESS_DURATION
},
configuration.getDateStart(),
gs31,
configuration.getDateEnd()
);
Collections.sort(observations);
retVal.setConfigParameter("observations", observations);
}
catch(WeatherDataSourceException ex)
catch(WeatherDataSourceException | ParseException ex)
{
throw new PreprocessorException(ex.getMessage());
}
......
/*
* Copyright (c) 2019 NIBIO <http://www.nibio.no/>.
*
* This file is part of VIPSLogic.
* VIPSLogic is free software: you can redistribute it and/or modify
* it under the terms of the NIBIO Open Source License as published by
* NIBIO, either version 1 of the License, or (at your option) any
* later version.
*
* VIPSLogic 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
* NIBIO Open Source License for more details.
*
* You should have received a copy of the NIBIO Open Source License
* along with VIPSLogic. If not, see <http://www.nibio.no/licenses/>.
*
*/
package no.nibio.vips.logic.scheduling.model.preprocessor;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import no.nibio.vips.entity.ModelConfiguration;
import no.nibio.vips.entity.WeatherObservation;
import no.nibio.vips.logic.entity.ForecastConfiguration;
import no.nibio.vips.logic.entity.PointOfInterestWeatherStation;
import no.nibio.vips.logic.scheduling.model.ModelRunPreprocessor;
import no.nibio.vips.logic.scheduling.model.PreprocessorException;
import no.nibio.vips.util.WeatherElements;
import no.nibio.vips.util.WeatherObservationListException;
import no.nibio.vips.util.WeatherUtil;
import no.nibio.vips.util.weather.WeatherDataSourceException;
import no.nibio.vips.util.weather.WeatherDataSourceUtil;
/**
* @copyright 2018 <a href="http://www.nibio.no/">NIBIO</a>
* @author Tor-Einar Skog <tor-einar.skog@nibio.no>
*/
public class SeptoriaReferenceHumidityModelPreprocessor extends ModelRunPreprocessor{
@Override
public ModelConfiguration getModelConfiguration(ForecastConfiguration configuration) throws PreprocessorException {
ModelConfiguration modelConfig = new ModelConfiguration();
// Which weather stations??
// Ilseng and Apelsvoll to start with ;-)
PointOfInterestWeatherStation station = (PointOfInterestWeatherStation) configuration.getWeatherStationPointOfInterestId();
//List<WeatherObservation> stationObs = getStationObs(station, configuration);
WeatherUtil wUtil = new WeatherUtil();
WeatherDataSourceUtil wdsUtil = new WeatherDataSourceUtil();
List<WeatherObservation> stationObs;
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date seasonStart = configuration.getDateStartInTimeZone();
Date seasonEnd = configuration.getDateEndInTimeZone();
try
{
if(configuration.getForecastModelConfigurationValue(this.getModelId() + "_SEASON_START") != null)
{
seasonStart = format.parse(configuration.getForecastModelConfigurationValue(this.getModelId() + "_SEASON_START"));
}
if(configuration.getForecastModelConfigurationValue(this.getModelId() + "_SEASON_END") != null)
{
seasonEnd = format.parse(configuration.getForecastModelConfigurationValue(this.getModelId() + "_SEASON_END"));
}
}
catch(ParseException ex)
{
// Keep calm and carry on?
}
try
{
stationObs = wdsUtil.getWeatherObservations(
station,
WeatherObservation.LOG_INTERVAL_ID_1H,
new String[]{
WeatherElements.LEAF_WETNESS_DURATION,
WeatherElements.RELATIVE_HUMIDITY_MEAN,
WeatherElements.PRECIPITATION,
WeatherElements.TEMPERATURE_MEAN
},
seasonStart,
seasonEnd);
// We need TM, UM and RR. BT is optional
//List<WeatherObservation> mandatory = wUtil.filterWeatherObservationsByParameter(stationObs, new HashSet<>(Arrays.asList("TM","UM","RR")));
//stationObs = wUtil.checkForAndFixHourlyTimeSeriesHolesMultiParameter(mandatory, 6);
stationObs = wUtil.filterWeatherObservationsByParameter(stationObs, new HashSet<>(Arrays.asList("TM","UM","RR")));
}
catch(WeatherDataSourceException ex)
{
throw new PreprocessorException("Problem with station " + station.getPointOfInterest().getName() + " (#" + station.getPointOfInterestId() + "): " + ex.getMessage());
}
// Checking for BT
//try
//{
List<WeatherObservation> BT = wUtil.filterWeatherObservationsByParameter(stationObs, new HashSet<>(Arrays.asList("BT")));
//stationObs.addAll(wUtil.checkForAndFixHourlyTimeSeriesHoles(BT, 6));
stationObs.addAll(BT);
//}
//catch(WeatherObservationListException ex)
//{
// System.out.println("Problem with station " + station.getPointOfInterest().getName() + " (#" + station.getPointOfInterestId() + "): " + ex.getMessage());
//}
modelConfig.setConfigParameter("observations", stationObs);
modelConfig.setModelId(this.getModelId());
modelConfig.setConfigParameter("timeZone", configuration.getTimeZone());
return modelConfig;
}
@Override
public String getModelId() {
return "SEPTREFHUM";
}
}
/*
* Copyright (c) 2019 NIBIO <http://www.nibio.no/>.
*
* This file is part of VIPSLogic.
* VIPSLogic is free software: you can redistribute it and/or modify
* it under the terms of the NIBIO Open Source License as published by
* NIBIO, either version 1 of the License, or (at your option) any
* later version.
*
* VIPSLogic 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
* NIBIO Open Source License for more details.
*
* You should have received a copy of the NIBIO Open Source License
* along with VIPSLogic. If not, see <http://www.nibio.no/licenses/>.
*
*/
package no.nibio.vips.logic.scheduling.tasks;
import it.sauronsoftware.cron4j.TaskExecutionContext;
import java.util.Map;
import no.nibio.vips.i18n.I18nImpl;
import no.nibio.vips.logic.entity.ForecastConfiguration;
import no.nibio.vips.logic.entity.ModelInformation;
import no.nibio.vips.logic.scheduling.SchedulingUtil;
import no.nibio.vips.logic.scheduling.VipsLogicTask;
import no.nibio.vips.logic.scheduling.model.PreprocessorException;
import no.nibio.vips.logic.util.RunModelException;
import no.nibio.vips.logic.util.SessionControllerGetter;
import no.nibio.web.forms.FormField;
/**
* @copyright 2013-2018 <a href="http://www.nibio.no/">NIBIO</a>
* @author Tor-Einar Skog <tor-einar.skog@nibio.no>
*/
public class RunForecastConfigurationsByIdTask extends VipsLogicTask{
private I18nImpl i18n;
//private boolean DEBUG=true;
@Override
public void execute(TaskExecutionContext tec) throws RuntimeException {
String[] forecastConfigurationIds;
if(this.getConfiguration() != null && this.getConfiguration().get("forecastConfigurationIds") != null)
{
forecastConfigurationIds = ((String) (this.getConfiguration().get("forecastConfigurationIds")[0])).split(",");
}
else
{
tec.setCompleteness(1.0);
tec.setStatusMessage("No forecast configurations were specified");
return;
}
String errorMessage = "";
tec.setCompleteness(0d);
Integer numberOfAttemptedForecastConfigurations = 0;
Integer numberOfCompletedForecastConfigurations = 0;
Boolean noForecastConfigurationsFound = forecastConfigurationIds.length == 0;
Map<String, ModelInformation> modelInformationMap = SessionControllerGetter.getForecastBean().getIndexedBatchableModelInformation();
for(String forecastConfigurationId:forecastConfigurationIds)
{
noForecastConfigurationsFound = false;
ForecastConfiguration forecastConfiguration = SessionControllerGetter.getForecastBean().getForecastConfiguration(Long.valueOf(forecastConfigurationId));
try
{
numberOfAttemptedForecastConfigurations++;
//System.out.println("Running forecast #" + forecastConfiguration.getForecastConfigurationId());
SessionControllerGetter.getForecastBean().runForecast(forecastConfiguration);
/*
if(DEBUG && totalNumberofForecastConfigurations == 2)
{
throw new RunModelException("This is a test!!!");
}*/
numberOfCompletedForecastConfigurations++;
//System.out.println("All went well");
}
catch (PreprocessorException | RunModelException ex)
{
errorMessage +=
SchedulingUtil.createSchedulingMessageHTML(
"Error with forecast #" + forecastConfiguration.getForecastConfigurationId() + " (" + forecastConfiguration.getLocationPointOfInterestId().getName() + " - " + modelInformationMap.get(forecastConfiguration.getModelId()).getDefaultName() + ")",
ex.getMessage(),
SchedulingUtil.MESSAGE_STATUS_DANGER)
;
//System.out.println("########################### Error caught: " + errorMessage);
//System.out.println("numberOfCompletedForecastConfigurations=" + numberOfCompletedForecastConfigurations);
//System.out.println("totalNumberofForecastConfigurations=" + totalNumberofForecastConfigurations);
//continue;
}
double completeness = (double) numberOfCompletedForecastConfigurations/forecastConfigurationIds.length;
tec.setCompleteness(completeness);
}
if(noForecastConfigurationsFound)
{
tec.setCompleteness(1.0);
tec.setStatusMessage("No current forecast configurations were found");
}
//System.out.println("Total completeness=" + tec.getTaskExecutor().getCompleteness());
if(tec.getTaskExecutor().getCompleteness() != 1.0)
{
//System.out.println("Error detected, RuntimeException thrown just after this");
tec.setStatusMessage(errorMessage);
throw new RuntimeException();
}
}
@Override
public boolean supportsStatusTracking()
{
return true;
}
@Override
public boolean supportsCompletenessTracking()
{
return true;
}
/**
*
* @return Form definition
*/
@Override
public String getConfigFormDefinition(String language) {
StringBuilder retVal = new StringBuilder()
.append("{")
.append(" \"fields\":[")
.append(" {")
.append(" \"name\":\"forecastConfigurationIds\",")
.append(" \"dataType\":\"").append(FormField.DATA_TYPE_STRING).append("\",")
.append(" \"fieldType\":\"").append(FormField.FIELD_TYPE_INPUT).append("\",")
.append(" \"nullValue\":\"\",")
.append(" \"required\":true")
.append(" }")
.append(" ]")
.append("}");
return retVal.toString();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment