Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
- changed intersection storage format
  • Loading branch information
temi committed Aug 19, 2024
1 parent 4972b19 commit c1b78fb
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 45 deletions.
4 changes: 2 additions & 2 deletions grails-app/services/au/org/ala/ecodata/MetadataService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -514,8 +514,8 @@ class MetadataService {
* uses the supplied field id.
* @param fid the field id.
*/
Map getGeographicFacetConfig(String fid) {
Map config = getGeographicConfig()
Map getGeographicFacetConfig(String fid, String hubId = null) {
Map config = getGeographicConfig(hubId)
Map facetConfig = null
config.contextual.each { String groupName, String groupFid ->
if (fid == groupFid) {
Expand Down
11 changes: 6 additions & 5 deletions grails-app/services/au/org/ala/ecodata/ProjectService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -1158,13 +1158,14 @@ class ProjectService {
Map orderLayerIntersectionsByAreaOfProjectSites (Map project) {
Map<String,Map<String,Double>> sumOfIntersectionsByLayer = [:].withDefault { [:].withDefault { 0 } }
Map orderedIntersectionsByArea = [:]
// get sites of projects;
Map config = metadataService.getGeographicConfig(project.hubId)
List layers = config.checkForBoundaryIntersectionInLayers
List projectSites = getRepresentativeSitesOfProject(project)
projectSites?.each { Map site ->
site.extent?.geometry?.get(SpatialService.INTERSECTION_AREA)?.each { String layerId, Map value ->
Set<String> keySet = value.keySet()
keySet.each { String layerValue ->
sumOfIntersectionsByLayer[layerId][layerValue] += value[layerValue]
layers.each { String layer ->
Map facet = metadataService.getGeographicFacetConfig(layer, project.hubId)
site.extent?.geometry?.get(SpatialService.INTERSECTION_AREA)?.get(facet.name)?.get(SiteService.INTERSECTION_CURRENT)?.each { String layerValue, value ->
sumOfIntersectionsByLayer[layer][layerValue] += value
}
}
}
Expand Down
30 changes: 29 additions & 1 deletion grails-app/services/au/org/ala/ecodata/SiteService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class SiteService {
static final PLANNING_SITE = 'Planning site'
static final EMSA_SITE = 'EMSA site'
static final REPORTING_SITE = 'Reporting site'
static final INTERSECTION_CURRENT = 'CURRENT'

def grailsApplication, activityService, projectService, commonService, webService, documentService, metadataService, cacheService
PermissionService permissionService
Expand Down Expand Up @@ -663,10 +664,37 @@ class SiteService {
log.error("No geometry for site: ${site.siteId}")
}

site.extent.geometry += lookupGeographicFacetsForSite(site, fids)
def geoFacets = lookupGeographicFacetsForSite(site, fids)
def intersectionsAreaByFacets = geoFacets.remove(SpatialService.INTERSECTION_AREA)
site.extent.geometry += geoFacets
mergeIntersectionsArea(site, intersectionsAreaByFacets)
}
}

/**
* The data is stored in the format -
* [ intersectionAreaByFacets: [ CURRENT: [act: 0.1, nsw: 0.6], cl22: [act: 0.1, nsw: 0.6]] ]
* @param site
* @param intersectionsAreaByFacets
* @return
*/
def mergeIntersectionsArea(Map site, Map intersectionsAreaByFacets) {
Map geometry = site.extent.geometry
List hubs = projectService.findHubIdOfProjects(site.projects)
String hubId = hubs?.size() == 1 ? hubs[0] : null
Map existingIntersectionsArea = geometry[SpatialService.INTERSECTION_AREA] = geometry[SpatialService.INTERSECTION_AREA] ?: [:]
intersectionsAreaByFacets?.each { String layer, Map nameAndValue ->
if (nameAndValue) {
Map facet = metadataService.getGeographicFacetConfig(layer, hubId)
existingIntersectionsArea[facet.name] = existingIntersectionsArea[facet.name]?: [:]
existingIntersectionsArea[facet.name][INTERSECTION_CURRENT] = nameAndValue
existingIntersectionsArea[facet.name][layer] = nameAndValue
}
}

site
}

/**
* get images for a list of sites. The images are associated with the point of interest of each site.
* @param ids
Expand Down
116 changes: 79 additions & 37 deletions src/test/groovy/au/org/ala/ecodata/ProjectServiceSpec.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ class ProjectServiceSpec extends MongoSpec implements ServiceUnitTest<ProjectSer
}

grailsApplication.config.collectory = [baseURL:collectoryBaseUrl, dataProviderUid:[merit:meritDataProvider, biocollect:biocollectDataProvider], collectoryIntegrationEnabled: true]
grailsApplication.config.app.facets.geographic = [
contextual: [
state : 'cl927',
elect : 'cl11163'
],
"checkForBoundaryIntersectionInLayers" : [ "cl927", "cl11163" ]
]
grailsApplication.mainContext.commonService.grailsApplication = grailsApplication
grailsApplication.mainContext.collectoryService.grailsApplication = grailsApplication
grailsApplication.mainContext.collectoryService.webService = webServiceStub
Expand All @@ -70,6 +77,7 @@ class ProjectServiceSpec extends MongoSpec implements ServiceUnitTest<ProjectSer
Project.collection.remove(new BasicDBObject())
ManagementUnit.collection.remove(new BasicDBObject())
AuditMessage.collection.remove(new BasicDBObject())
Site.collection.remove(new BasicDBObject())
}

def cleanup() {
Expand Down Expand Up @@ -918,40 +926,62 @@ class ProjectServiceSpec extends MongoSpec implements ServiceUnitTest<ProjectSer
void "orderLayerIntersectionsByAreaOfProjectSites should sum proportions order intersections by descending order"() {
setup:
Project project1 = new Project(projectId: '111', name: "Project 111", hubId:"12345", isMERIT: true).save()
Site site1 = new Site(siteId: 's1', name: "Site 1", type: "compound", projects: ['111'], extent: [ source: "point", geometry: [intersectionAreaByFacets: ["cl11163": ["bean": 0.1, "canberra": 0.2, "fenner": 0.25]]]]).save()
Site site2 = new Site(siteId: 's2', name: "Site 2", type: "compound", projects: ['111'], extent: [ source: "point", geometry: [intersectionAreaByFacets: ["cl11163": ["bean": 0.7, "canberra": 0.4, "fenner": 0.5]]]]).save()
project1.metaClass.getDbo = { new BasicDBObject(project1.properties) }
Map projectMap
projectMap = service.toMap(project1, 'all')
Map result
Project project1
metadataService.getGeographicConfig(_) >> [
contextual: [
elect : 'cl11163'
],
"checkForBoundaryIntersectionInLayers" : [ "cl11163" ]
]
metadataService.getGeographicFacetConfig("cl11163", "12345") >> [name: "elect", grouped: true]
Project.withSession { session ->
project1 = new Project(projectId: '111', name: "Project 111", hubId:"12345", isMERIT: true).save(flush: true, failOnError: true)
Site site1 = new Site(siteId: 's1', name: "Site 1", type: "compound", projects: ['111'], extent: [ source: "point", geometry: [intersectionAreaByFacets: ["elect": ["CURRENT": ["bean": 0.1, "canberra": 0.2, "fenner": 0.25]]]]]).save(flush: true)
Site site2 = new Site(siteId: 's2', name: "Site 2", type: "compound", projects: ['111'], extent: [ source: "point", geometry: [intersectionAreaByFacets: ["elect": ["CURRENT": ["bean": 0.7, "canberra": 0.4, "fenner": 0.5]]]]]).save(flush: true)
project1.metaClass.getDbo = { new BasicDBObject(project1.properties) }
session.flush()
projectMap = service.toMap(project1, ProjectService.ALL)
}
when:
Map result = service.orderLayerIntersectionsByAreaOfProjectSites(projectMap)
Project.withSession {
result = service.orderLayerIntersectionsByAreaOfProjectSites(projectMap)
}
then:
result.size() == 1
result."cl11163"[0] == "bean"
result."cl11163"[1] == "fenner"
result."cl11163"[2] == "canberra"
result["cl11163"][0] == "bean"
result["cl11163"][1] == "fenner"
result["cl11163"][2] == "canberra"
}
void "getRepresentativeSitesOfProject should get EMSA site or Reporting sites only" () {
setup:
ManagementUnit mu = new ManagementUnit(managementUnitId: 'mu1', name: "Management Unit 1", managementUnitSiteId: 's4').save()
Project project1 = new Project(projectId: '111', name: "Project 111", hubId:"12345", isMERIT: true, managementUnitId: 'mu1')
project1.save(flush: true)
Site site1 = new Site(siteId: 's1', name: "Site 1", type: "compound", projects: ['111'], extent: [ source: "point", geometry: [intersectionAreaByFacets: ["cl11163": ["bean": 0.1, "canberra": 0.2, "fenner": 0.25]]]]).save(flush: true)
Site site2 = new Site(siteId: 's2', name: "Site 2", type: "compound", projects: ['111'], extent: [ source: "point", geometry: [intersectionAreaByFacets: ["cl11163": ["bean": 0.7, "canberra": 0.4, "fenner": 0.5]]]]).save(flush: true)
Site site3 = new Site(siteId: 's3', name: "Site 3", externalIds: [[idType: ExternalId.IdType.MONITOR_PROTOCOL_INTERNAL_ID, externalId: '1']], projects: ['111'], extent: [ source: "point", geometry: [intersectionAreaByFacets: ["cl11163": ["bean": 0.0, "canberra": 0.1, "fenner": 0.6]]]]).save(flush: true)
Site site4 = new Site(siteId: 's4', name: "Site 4", type: "worksArea", extent: [ source: "point", geometry: [intersectionAreaByFacets: ["cl11163": ["bean": 0.7, "canberra": 0.4, "fenner": 0.5]]]]).save(flush: true)
Site site5 = new Site(siteId: 's5', name: "Site 5", type: "worksArea", projects: ['111'], extent: [ source: "point", geometry: [intersectionAreaByFacets: ["cl11163": ["bean": 0.7, "canberra": 0.4, "fenner": 0.5]]]]).save(flush: true)
project1.metaClass.getDbo = { new BasicDBObject(project1.properties) }
Map projectMap
projectMap = service.toMap(project1, ProjectService.ALL)
Site site1, site2, site3, site4, site5
Project project1
ManagementUnit mu
List result
Project.withSession { session ->
project1 = new Project(projectId: '111', name: "Project 111", hubId:"12345", isMERIT: true, managementUnitId: 'mu1').save(flush: true)
mu = new ManagementUnit(managementUnitId: 'mu1', name: "Management Unit 1", managementUnitSiteId: 's4').save(flush: true)
site1 = new Site(siteId: 's1', name: "Site 1", type: "compound", projects: ['111'], extent: [ source: "point", geometry: [intersectionAreaByFacets: ["cl11163": ["bean": 0.1, "canberra": 0.2, "fenner": 0.25]]]]).save(flush: true)
site2 = new Site(siteId: 's2', name: "Site 2", type: "compound", projects: ['111'], extent: [ source: "point", geometry: [intersectionAreaByFacets: ["cl11163": ["bean": 0.7, "canberra": 0.4, "fenner": 0.5]]]]).save(flush: true)
site3 = new Site(siteId: 's3', name: "Site 3", externalIds: [[idType: ExternalId.IdType.MONITOR_PROTOCOL_INTERNAL_ID, externalId: '1']], projects: ['111'], extent: [ source: "point", geometry: [intersectionAreaByFacets: ["cl11163": ["bean": 0.0, "canberra": 0.1, "fenner": 0.6]]]]).save(flush: true)
site4 = new Site(siteId: 's4', name: "Site 4", type: "worksArea", extent: [ source: "point", geometry: [intersectionAreaByFacets: ["cl11163": ["bean": 0.7, "canberra": 0.4, "fenner": 0.5]]]]).save(flush: true)
site5 = new Site(siteId: 's5', name: "Site 5", type: "worksArea", projects: ['111'], extent: [ source: "point", geometry: [intersectionAreaByFacets: ["cl11163": ["bean": 0.7, "canberra": 0.4, "fenner": 0.5]]]]).save(flush: true)
project1.metaClass.getDbo = { new BasicDBObject(project1.properties) }
session.flush()
projectMap = service.toMap(project1, ProjectService.ALL)
}
when: // returns reporting and EMSA sites Only
List result = service.getRepresentativeSitesOfProject(projectMap)
Project.withSession {
result = service.getRepresentativeSitesOfProject(projectMap)
}
then:
result.size() == 3
Expand All @@ -960,13 +990,17 @@ class ProjectServiceSpec extends MongoSpec implements ServiceUnitTest<ProjectSer
result.siteId[2] == 's3'
when: // returns planning/project extent sites
site1.type = Site.TYPE_PROJECT_AREA
site1.save()
site2.type = Site.TYPE_WORKS_AREA
site2.save()
site3.delete()
projectMap = service.toMap(project1, ProjectService.ALL)
result = service.getRepresentativeSitesOfProject(projectMap)
Project.withSession { session ->
site1.type = Site.TYPE_PROJECT_AREA
site1.save(flush: true)
site2.type = Site.TYPE_WORKS_AREA
site2.save(flush: true)
site3.delete(flush: true)
project1.metaClass.getDbo = { new BasicDBObject(project1.properties) }
session.flush()
projectMap = service.toMap(project1, ProjectService.ALL)
result = service.getRepresentativeSitesOfProject(projectMap)
}
then:
result.size() == 3
Expand All @@ -975,22 +1009,30 @@ class ProjectServiceSpec extends MongoSpec implements ServiceUnitTest<ProjectSer
result.siteId[2] == 's5'
when: // returns Management Unit boundaries
site1.projects = site2.projects = site5.projects = []
site1.save()
site2.save()
site5.save()
projectMap = service.toMap(project1, ProjectService.ALL)
result = service.getRepresentativeSitesOfProject(projectMap)
Project.withSession { session ->
site1.projects = site2.projects = site5.projects = []
site1.save(flush: true)
site2.save(flush: true)
site5.save(flush: true)
project1.metaClass.getDbo = { new BasicDBObject(project1.properties) }
session.flush()
projectMap = service.toMap(project1, ProjectService.ALL)
result = service.getRepresentativeSitesOfProject(projectMap)
}
then:
result.size() == 1
result.siteId[0] == 's4'
when:// returns empty
project1.managementUnitId = null
project1.save()
projectMap = service.toMap(project1, ProjectService.ALL)
result = service.getRepresentativeSitesOfProject(projectMap)
Project.withSession { session ->
project1.managementUnitId = null
project1.save(flush: true)
project1.metaClass.getDbo = { new BasicDBObject(project1.properties) }
session.flush()
projectMap = service.toMap(project1, ProjectService.ALL)
result = service.getRepresentativeSitesOfProject(projectMap)
}
then:
result.isEmpty()
Expand Down
4 changes: 4 additions & 0 deletions src/test/groovy/au/org/ala/ecodata/SiteServiceSpec.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class SiteServiceSpec extends MongoSpec implements ServiceUnitTest<SiteService>
def webServiceMock = Mock(WebService)
def metadataServiceMock = Mock(MetadataService)
def spatialServiceMock = Mock(SpatialService)
def projectService = Mock(ProjectService)
CommonService commonService = new CommonService()
void setup() {
//defineBeans {
Expand All @@ -35,6 +36,7 @@ class SiteServiceSpec extends MongoSpec implements ServiceUnitTest<SiteService>
service.grailsApplication = grailsApplication
service.metadataService = metadataServiceMock
service.spatialService = spatialServiceMock
service.projectService = projectService
// grailsApplication.mainContext.registerSingleton('commonService', CommonService)
// grailsApplication.mainContext.commonService.grailsApplication = grailsApplication
}
Expand Down Expand Up @@ -192,6 +194,7 @@ class SiteServiceSpec extends MongoSpec implements ServiceUnitTest<SiteService>
def "New sites without a centroid should have one assigned"() {
when:
def result
projectService.findHubIdOfProjects(_) >> []
Site.withSession { session ->
result = service.create([name: 'Site 1', extent: [source: 'pid', geometry: [type: 'pid', pid: 'cl123']]])
session.flush()
Expand Down Expand Up @@ -307,6 +310,7 @@ class SiteServiceSpec extends MongoSpec implements ServiceUnitTest<SiteService>
def "The site area is calculated from the FeatureCollection for a compound site"() {
setup:
projectService.findHubIdOfProjects(_) >> []
def coordinates = [[148.260498046875, -37.26530995561874], [148.260498046875, -37.26531995561874], [148.310693359375, -37.26531995561874], [148.310693359375, -37.26531995561874], [148.260498046875, -37.26530995561874]]
def extent = buildExtent('drawn', 'Polygon', coordinates)
Map site = [type: Site.TYPE_COMPOUND, extent: extent, features: [
Expand Down

0 comments on commit c1b78fb

Please sign in to comment.