Skip to content

Commit f803982

Browse files
committed
- checks species match using name matching server
1 parent 1ac3b7e commit f803982

File tree

4 files changed

+97
-42
lines changed

4 files changed

+97
-42
lines changed

grails-app/conf/application.groovy

+1
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,7 @@ if (!ala.baseURL) {
503503
}
504504
bie.ws.url = "https://bie-ws.ala.org.au/"
505505
bie.url = "https://bie.ala.org.au/"
506+
namesmatching.url = "https://namematching-ws-test.ala.org.au/"
506507

507508
if (!collectory.baseURL) {
508509
//collectory.baseURL = "https://collectory-dev.ala.org.au/"

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

+20-13
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class ParatooService {
7777
RecordService recordService
7878
MetadataService metadataService
7979
UserService userService
80+
SpeciesReMatchService speciesReMatchService
8081

8182
/**
8283
* The rules we use to find projects eligible for use by paratoo are:
@@ -2053,7 +2054,7 @@ class ParatooService {
20532054
/**
20542055
* Transforms a species name to species object used by ecodata.
20552056
* e.g. Acacia glauca [Species] (scientific: Acacia glauca Willd.)
2056-
* [name: "Acacia glauca Willd.", scientificName: "Acacia glauca Willd.", guid: "A_GUID"]
2057+
* [name: "Acacia glauca Willd.", scientificName: "Acacia glauca Willd.", commonName: "Acacia glauca", guid: "A_GUID"]
20572058
* Guid is necessary to generate species occurrence record. Guid is found by searching the species name with BIE. If not found, then a default value is added.
20582059
* @param name
20592060
* @return
@@ -2064,28 +2065,34 @@ class ParatooService {
20642065
}
20652066

20662067
String regex = "([^\\[\\(]*)(?:\\[(.*)\\])?\\s*(?:\\(scientific:\\s*(.*?)\\))?"
2068+
String commonName, scientificName = name
20672069
Pattern pattern = Pattern.compile(regex)
20682070
Matcher matcher = pattern.matcher(name)
2069-
Map result = [name: name, scientificName: name, commonName: name, outputSpeciesId: UUID.randomUUID().toString()]
2071+
Map result = [scientificName: name, commonName: name, outputSpeciesId: UUID.randomUUID().toString()]
20702072

20712073
if (matcher.find()) {
2072-
String commonName = matcher.group(1)?.trim()
2073-
String scientificName = matcher.group(3)?.trim()
2074-
result.commonName = commonName ?: result.commonName
2074+
commonName = matcher.group(1)?.trim()
2075+
scientificName = matcher.group(3)?.trim()
20752076
result.taxonRank = matcher.group(2)?.trim()
2076-
result.scientificName = scientificName ?: commonName ?: result.scientificName
2077-
result.name = scientificName ?: commonName ?: result.name
2077+
result.scientificName = scientificName
2078+
result.commonName = commonName
20782079
}
20792080

2080-
metadataService.autoPopulateSpeciesData(result)
2081+
Map resp = speciesReMatchService.searchByName(scientificName)
2082+
if (resp) {
2083+
result.putAll(resp)
2084+
}
20812085
// try again with common name
2082-
if ((result.guid == null) && result.commonName) {
2083-
def speciesObject = [scientificName: result.commonName]
2084-
metadataService.autoPopulateSpeciesData(speciesObject)
2085-
result.guid = speciesObject.guid
2086-
result.scientificName = result.scientificName ?: speciesObject.scientificName
2086+
if ((result.guid == null) && commonName) {
2087+
resp = speciesReMatchService.searchByName(commonName)
2088+
if (resp) {
2089+
result.putAll(resp)
2090+
result.commonName = commonName
2091+
}
20872092
}
20882093

2094+
result.name = result.commonName ? result.scientificName ? "${result.scientificName} (${result.commonName})" : result.commonName : result.scientificName
2095+
20892096
// record is only created if guid is present
20902097
result.guid = result.guid ?: Record.UNMATCHED_GUID
20912098
result

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

+32
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,36 @@ class SpeciesReMatchService {
9090
webService.getJson(url)
9191
})
9292
}
93+
94+
Map searchByName (String name, boolean addDetails = false) {
95+
Map result = searchNameMatchingServer(name)
96+
if (result) {
97+
Map resp = [
98+
scientificName: result.scientificName,
99+
commonName: result.vernacularName,
100+
guid: result.taxonConceptID,
101+
taxonRank: result.rank
102+
]
103+
104+
if(addDetails) {
105+
resp.put('details', result)
106+
}
107+
108+
return resp
109+
}
110+
}
111+
112+
Map searchNameMatchingServer(String name) {
113+
name = name?.toLowerCase() ?: ""
114+
cacheService.get('name-matching-server-' + name, {
115+
def encodedQuery = URLEncoder.encode(name ?: '', "UTF-8")
116+
def url = "${grailsApplication.config.getProperty('namesmatching.url')}api/search?q=${encodedQuery}"
117+
def resp = webService.getJson(url)
118+
if (!resp.success) {
119+
return null
120+
}
121+
122+
resp
123+
})
124+
}
93125
}

src/test/groovy/au/org/ala/ecodata/ParatooServiceSpec.groovy

+44-29
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class ParatooServiceSpec extends MongoSpec implements ServiceUnitTest<ParatooSer
2626
TokenService tokenService = Mock(TokenService)
2727
SettingService settingService = Mock(SettingService)
2828
MetadataService metadataService = Mock(MetadataService)
29+
SpeciesReMatchService speciesReMatchService = Mock(SpeciesReMatchService)
2930
ActivityService activityService = Mock(ActivityService)
3031
RecordService recordService = Mock(RecordService)
3132
UserService userService = Mock(UserService)
@@ -55,6 +56,7 @@ class ParatooServiceSpec extends MongoSpec implements ServiceUnitTest<ParatooSer
5556
service.recordService = recordService
5657
service.cacheService = new CacheService()
5758
service.userService = userService
59+
service.speciesReMatchService = speciesReMatchService
5860

5961
JSON.registerObjectMarshaller(new MapMarshaller())
6062
JSON.registerObjectMarshaller(new CollectionMarshaller())
@@ -654,25 +656,6 @@ class ParatooServiceSpec extends MongoSpec implements ServiceUnitTest<ParatooSer
654656
result == ""
655657
}
656658

657-
void "transformSpeciesName should convert paratoo species name to object correctly"() {
658-
when:
659-
Map result = service.transformSpeciesName("Acacia glauca [Species] (scientific: Acacia glauca Willd.)")
660-
String outputSpeciesId = result.remove("outputSpeciesId")
661-
then:
662-
outputSpeciesId != null
663-
result == [name: "Acacia glauca Willd.", scientificName: "Acacia glauca Willd.", guid: "A_GUID", commonName: "Acacia glauca", taxonRank: "Species"]
664-
2 * metadataService.autoPopulateSpeciesData(_) >> null
665-
666-
when: // no scientific name
667-
result = service.transformSpeciesName("Frogs [Class] (scientific: )")
668-
outputSpeciesId = result.remove("outputSpeciesId")
669-
670-
then:
671-
outputSpeciesId != null
672-
result == [name: "Frogs", scientificName: "Frogs", guid: "A_GUID", commonName: "Frogs", taxonRank: "Class"]
673-
2 * metadataService.autoPopulateSpeciesData(_) >> null
674-
}
675-
676659
void "buildRelationshipTree should build relationship tree correctly"() {
677660
given:
678661
def properties = [
@@ -723,6 +706,25 @@ class ParatooServiceSpec extends MongoSpec implements ServiceUnitTest<ParatooSer
723706
relationships["fauna-survey"].contains("fauna-observation")
724707
}
725708

709+
void "transformSpeciesName should convert paratoo species name to object correctly"() {
710+
when:
711+
Map result = service.transformSpeciesName("Acacia glauca [Species] (scientific: Acacia glauca Willd.)")
712+
String outputSpeciesId = result.remove("outputSpeciesId")
713+
then:
714+
outputSpeciesId != null
715+
result == [name: "Acacia glauca Willd. (Acacia glauca)", scientificName: "Acacia glauca Willd.", guid: "A_GUID", commonName: "Acacia glauca", taxonRank: "Species"]
716+
2 * speciesReMatchService.searchByName(_) >> null
717+
718+
when: // no scientific name
719+
result = service.transformSpeciesName("Frogs [Class] (scientific: )")
720+
outputSpeciesId = result.remove("outputSpeciesId")
721+
722+
then:
723+
outputSpeciesId != null
724+
result == [name: "Frogs", scientificName: "", guid: "A_GUID", commonName: "Frogs", taxonRank: "Class"]
725+
2 * speciesReMatchService.searchByName(_) >> null
726+
}
727+
726728
void "buildTreeFromParentChildRelationships should build tree correctly"() {
727729
given:
728730
def relationships = [
@@ -1399,13 +1401,19 @@ class ParatooServiceSpec extends MongoSpec implements ServiceUnitTest<ParatooSer
13991401
result.lut.remove('outputSpeciesId')
14001402

14011403
then:
1404+
1 * speciesReMatchService.searchByName(_) >> [
1405+
commonName: "Cat",
1406+
scientificName: "Felis catus",
1407+
guid: "TAXON_ID",
1408+
taxonRank: "species"
1409+
]
14021410
result == [
14031411
lut: [
14041412
commonName: "Cat",
1405-
name: "Cat",
1406-
taxonRank: null,
1407-
scientificName: "Cat",
1408-
guid: "A_GUID"
1413+
name: "Felis catus (Cat)",
1414+
taxonRank: "species",
1415+
scientificName: "Felis catus",
1416+
guid: "TAXON_ID"
14091417
]
14101418
]
14111419

@@ -1417,18 +1425,25 @@ class ParatooServiceSpec extends MongoSpec implements ServiceUnitTest<ParatooSer
14171425
]
14181426
]
14191427
output = [
1420-
lut: "Cat"
1428+
lut: "Cats [Species] (scientific: Felis catus)"
14211429
]
14221430
result = service.recursivelyTransformData(dataModel, output, formName, 1, null)
14231431
result.lut.remove('outputSpeciesId')
14241432
then:
1433+
1 * speciesReMatchService.searchByName("Felis catus") >> null
1434+
1 * speciesReMatchService.searchByName("Cats") >> [
1435+
commonName: "Cat",
1436+
scientificName: "Felis catus",
1437+
guid: "TAXON_ID",
1438+
taxonRank: "species"
1439+
]
14251440
result == [
14261441
lut: [
1427-
commonName: "Cat",
1428-
name: "Cat",
1429-
taxonRank: null,
1430-
scientificName: "Cat",
1431-
guid: "A_GUID"
1442+
commonName: "Cats",
1443+
name: "Felis catus (Cats)",
1444+
taxonRank: "species",
1445+
scientificName: "Felis catus",
1446+
guid: "TAXON_ID"
14321447
]
14331448
]
14341449
}

0 commit comments

Comments
 (0)