Skip to content

Commit dc6099e

Browse files
committed
- added fauna plot to site - site with features are now of compound type - plot update will now create new site
1 parent 8933698 commit dc6099e

File tree

3 files changed

+70
-24
lines changed

3 files changed

+70
-24
lines changed

grails-app/domain/au/org/ala/ecodata/Site.groovy

+10
Original file line numberDiff line numberDiff line change
@@ -181,4 +181,14 @@ class Site {
181181
status != Status.DELETED
182182
}.find()
183183
}
184+
185+
static List<Site> findAllByExternalId(ExternalId.IdType idType, String externalId, Map params) {
186+
where {
187+
externalIds {
188+
idType == idType
189+
externalId == externalId
190+
}
191+
status != Status.DELETED
192+
}.list(params)
193+
}
184194
}

grails-app/services/au/org/ala/ecodata/ParatooService.groovy

+16-6
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,10 @@ class ParatooService {
588588
List features = geoJson?.features ?: []
589589
geoJson.remove('features')
590590
siteProps.features = features
591-
siteProps.type = Site.TYPE_SURVEY_AREA
591+
if (features)
592+
siteProps.type = Site.TYPE_COMPOUND
593+
else
594+
siteProps.type = Site.TYPE_SURVEY_AREA
592595
siteProps.publicationStatus = PublicationStatus.PUBLISHED
593596
siteProps.projects = [project.projectId]
594597
String externalId = geoJson.properties?.externalId
@@ -598,18 +601,19 @@ class ParatooService {
598601
Site site
599602
// create new site for every non-plot submission
600603
if (config.usesPlotLayout) {
601-
site = Site.findByExternalId(ExternalId.IdType.MONITOR_PLOT_GUID, externalId)
602-
if (site?.features) {
603-
siteProps.features?.addAll(site.features)
604-
}
604+
List sites = Site.findAllByExternalId(ExternalId.IdType.MONITOR_PLOT_GUID, externalId, [sort: "lastUpdated", order: "desc"])
605+
if (sites)
606+
site = sites.first()
605607
}
606608

607609
Map result
608-
if (!site) {
610+
// If the plot layout has been updated, create a new site
611+
if (!site || isUpdatedPlotLayout(site, observation, config)) {
609612
result = siteService.create(siteProps)
610613
} else {
611614
result = [siteId: site.siteId]
612615
}
616+
613617
if (result.error) {
614618
// Don't treat this as a fatal error for the purposes of responding to the paratoo request
615619
log.error("Error creating a site for survey " + collection.orgMintedUUID + ", project " + project.projectId + ": " + result.error)
@@ -619,6 +623,12 @@ class ParatooService {
619623
[siteId:siteId, name:siteProps?.name]
620624
}
621625

626+
private static boolean isUpdatedPlotLayout (Site site, Map observation, ParatooProtocolConfig config) {
627+
Date localSiteUpdated = site.lastUpdated
628+
Date plotLayoutUpdated = config.getPlotLayoutUpdatedAt(observation)
629+
plotLayoutUpdated?.after(localSiteUpdated) ?: false
630+
}
631+
622632
private Map syncParatooProtocols(List<Map> protocols) {
623633
Map result = [errors: [], messages: []]
624634
List guids = []

src/main/groovy/au/org/ala/ecodata/paratoo/ParatooProtocolConfig.groovy

+44-18
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import org.locationtech.jts.geom.Geometry
1212
@Slf4j
1313
@JsonIgnoreProperties(['metaClass', 'errors', 'expandoMetaClass'])
1414
class ParatooProtocolConfig {
15-
15+
static final String FAUNA_PLOT = 'Fauna plot'
16+
static final String CORE_PLOT = 'Core monitoring plot'
1617
String name
1718
String apiEndpoint
1819
boolean usesPlotLayout = true
@@ -26,7 +27,9 @@ class ParatooProtocolConfig {
2627
String plotVisitPath = 'plot_visit'
2728
String plotLayoutPath = "${plotVisitPath}.plot_layout"
2829
String plotLayoutIdPath = "${plotLayoutPath}.id"
30+
String plotLayoutUpdatedAtPath = "${plotLayoutPath}.updatedAt"
2931
String plotLayoutPointsPath = "${plotLayoutPath}.plot_points"
32+
String faunaPlotPointPath = "${plotLayoutPath}.fauna_plot_point"
3033
String plotSelectionPath = "${plotLayoutPath}.plot_selection"
3134
String plotLayoutDimensionLabelPath = "${plotLayoutPath}.plot_dimensions.label"
3235
String plotLayoutTypeLabelPath = "${plotLayoutPath}.plot_type.label"
@@ -79,6 +82,16 @@ class ParatooProtocolConfig {
7982
return removeMilliseconds(date)
8083
}
8184

85+
Date getPlotLayoutUpdatedAt(Map surveyData) {
86+
def date = getProperty(surveyData, plotLayoutUpdatedAtPath)
87+
if (!date) {
88+
date = getPropertyFromSurvey(surveyData, plotLayoutUpdatedAtPath)
89+
}
90+
91+
date = getFirst(date)
92+
date ? DateUtil.parseWithMilliseconds(date) : null
93+
}
94+
8295
Map getSurveyId(Map surveyData) {
8396
if(surveyIdPath == null || surveyData == null) {
8497
return null
@@ -203,7 +216,11 @@ class ParatooProtocolConfig {
203216
geoJson = extractSiteDataFromPlotVisit(output)
204217
// get list of all features associated with observation
205218
if (geoJson && form && output) {
206-
geoJson.features = extractFeatures(output, form)
219+
List features = extractFeatures(output, form)
220+
if (features) {
221+
features.addAll(geoJson.features?:[])
222+
geoJson = createConvexHullGeoJSON(features, geoJson.properties.name, geoJson.properties.externalId)
223+
}
207224
}
208225
}
209226
else if (geometryPath) {
@@ -212,20 +229,10 @@ class ParatooProtocolConfig {
212229
else if (form && output) {
213230
List features = extractFeatures(output, form)
214231
if (features) {
215-
List featureGeometries = features.collect { it.geometry }
216-
Geometry geometry = GeometryUtils.getFeatureCollectionConvexHull(featureGeometries)
217232
String startDateInString = getStartDate(output)
218233
startDateInString = DateUtil.convertUTCDateToStringInTimeZone(startDateInString, clientTimeZone?:TimeZone.default)
219234
String name = "${form.name} site - ${startDateInString}"
220-
geoJson = [
221-
type: 'Feature',
222-
geometry: GeometryUtils.geometryToGeoJsonMap(geometry),
223-
properties: [
224-
name: name,
225-
description: "${name} (convex hull of all features)",
226-
],
227-
features: features
228-
]
235+
geoJson = createConvexHullGeoJSON(features, name)
229236
}
230237
}
231238

@@ -313,6 +320,8 @@ class ParatooProtocolConfig {
313320
log.warn("No plot_layout found in survey at path ${plotLayoutIdPath}")
314321
return null
315322
}
323+
else
324+
plotLayoutId = plotLayoutId.toString()
316325
List plotLayoutPoints = getProperty(surveyData, plotLayoutPointsPath)
317326
Map plotSelection = getProperty(surveyData, plotSelectionPath)
318327
Map plotSelectionGeoJson = plotSelectionToGeoJson(plotSelection)
@@ -322,16 +331,33 @@ class ParatooProtocolConfig {
322331

323332
String name = plotSelectionGeoJson.properties.name + ' - ' + plotLayoutTypeLabel + ' (' + plotLayoutDimensionLabel + ')'
324333

325-
Map plotGeoJson = createFeatureFromGeoJSON(plotLayoutPoints, name, plotLayoutId, plotSelectionGeoJson?.properties?.notes)
326-
327-
//Map faunaPlotGeoJson = toGeometry(plotLayout.fauna_plot_point)
334+
Map plotGeoJson = createFeatureFromGeoJSON(plotLayoutPoints, name, plotLayoutId, "${CORE_PLOT} ${plotSelectionGeoJson?.properties?.notes?:""}")
335+
List faunaPlotPoints = getProperty(surveyData, faunaPlotPointPath)
336+
Map faunaPlotGeoJson = createFeatureFromGeoJSON(faunaPlotPoints, name, plotLayoutId, "${FAUNA_PLOT} ${plotSelectionGeoJson?.properties?.notes?:""}")
328337

329-
// TODO maybe turn this into a feature with properties to distinguish the fauna plot?
330-
// Or a multi-polygon?
338+
if (faunaPlotGeoJson) {
339+
List features = [plotGeoJson, faunaPlotGeoJson]
340+
plotGeoJson = createConvexHullGeoJSON(features, name, plotLayoutId)
341+
}
331342

332343
plotGeoJson
333344
}
334345

346+
static Map createConvexHullGeoJSON (List features, String name, String externalId = "") {
347+
List featureGeometries = features.collect { it.geometry }
348+
Geometry geometry = GeometryUtils.getFeatureCollectionConvexHull(featureGeometries)
349+
[
350+
type: 'Feature',
351+
geometry: GeometryUtils.geometryToGeoJsonMap(geometry),
352+
properties: [
353+
name: name,
354+
externalId: externalId,
355+
description: "${name} (convex hull of all features)",
356+
],
357+
features: features
358+
]
359+
}
360+
335361
static Map createFeatureFromGeoJSON(List plotLayoutPoints, String name, def plotLayoutId, String notes = "") {
336362
Map plotGeometry = toGeometry(plotLayoutPoints)
337363
createFeatureObject(plotGeometry, name, plotLayoutId, notes)

0 commit comments

Comments
 (0)