Skip to content

Commit 1984f24

Browse files
authored
Merge pull request #954 from AtlasOfLivingAustralia/feature/issues951
#951
2 parents 7184cb7 + f803982 commit 1984f24

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:
@@ -2054,7 +2055,7 @@ class ParatooService {
20542055
/**
20552056
* Transforms a species name to species object used by ecodata.
20562057
* e.g. Acacia glauca [Species] (scientific: Acacia glauca Willd.)
2057-
* [name: "Acacia glauca Willd.", scientificName: "Acacia glauca Willd.", guid: "A_GUID"]
2058+
* [name: "Acacia glauca Willd.", scientificName: "Acacia glauca Willd.", commonName: "Acacia glauca", guid: "A_GUID"]
20582059
* 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.
20592060
* @param name
20602061
* @return
@@ -2065,28 +2066,34 @@ class ParatooService {
20652066
}
20662067

20672068
String regex = "([^\\[\\(]*)(?:\\[(.*)\\])?\\s*(?:\\(scientific:\\s*(.*?)\\))?"
2069+
String commonName, scientificName = name
20682070
Pattern pattern = Pattern.compile(regex)
20692071
Matcher matcher = pattern.matcher(name)
2070-
Map result = [name: name, scientificName: name, commonName: name, outputSpeciesId: UUID.randomUUID().toString()]
2072+
Map result = [scientificName: name, commonName: name, outputSpeciesId: UUID.randomUUID().toString()]
20712073

20722074
if (matcher.find()) {
2073-
String commonName = matcher.group(1)?.trim()
2074-
String scientificName = matcher.group(3)?.trim()
2075-
result.commonName = commonName ?: result.commonName
2075+
commonName = matcher.group(1)?.trim()
2076+
scientificName = matcher.group(3)?.trim()
20762077
result.taxonRank = matcher.group(2)?.trim()
2077-
result.scientificName = scientificName ?: commonName ?: result.scientificName
2078-
result.name = scientificName ?: commonName ?: result.name
2078+
result.scientificName = scientificName
2079+
result.commonName = commonName
20792080
}
20802081

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

2095+
result.name = result.commonName ? result.scientificName ? "${result.scientificName} (${result.commonName})" : result.commonName : result.scientificName
2096+
20902097
// record is only created if guid is present
20912098
result.guid = result.guid ?: Record.UNMATCHED_GUID
20922099
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)