001/* 002 * Copyright 2020 Global Biodiversity Information Facility (GBIF) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.gbif.api.model.checklistbank; 017 018import org.gbif.api.SerdeTestUtils; 019import org.gbif.api.vocabulary.NamePart; 020import org.gbif.api.vocabulary.NameType; 021import org.gbif.api.vocabulary.Rank; 022 023import java.io.IOException; 024 025import org.junit.jupiter.api.Test; 026 027import static org.junit.jupiter.api.Assertions.assertEquals; 028import static org.junit.jupiter.api.Assertions.assertFalse; 029import static org.junit.jupiter.api.Assertions.assertNull; 030import static org.junit.jupiter.api.Assertions.assertTrue; 031 032public class ParsedNameTest { 033 034 @Test 035 public void testCanonicalName() { 036 ParsedName pn = new ParsedName(); 037 pn.setGenusOrAbove("Abies"); 038 assertEquals("Abies", pn.canonicalName()); 039 040 pn.setSpecificEpithet("alba"); 041 assertEquals("Abies alba", pn.canonicalName()); 042 043 pn = new ParsedName(); 044 pn.setGenusOrAbove("Abies"); 045 pn.setSpecificEpithet("alba"); 046 pn.setRank(Rank.VARIETY); 047 pn.setAuthorship("Mill."); 048 pn.setBracketAuthorship("Carl."); 049 pn.setNotho(NamePart.GENERIC); 050 pn.setInfraSpecificEpithet("alpina"); 051 pn.setYear("1887"); 052 pn.setSensu("Döring"); 053 pn.setRemarks("lost"); 054 pn.setNomStatus("nom. illeg."); 055 pn.setParsedPartially(true); 056 057 assertEquals("Abies alba alpina", pn.canonicalName()); 058 assertEquals("×Abies alba var. alpina", pn.canonicalNameWithMarker()); 059 assertEquals("×Abies alba var. alpina (Carl.) Mill., 1887", pn.canonicalNameComplete()); 060 assertEquals("Abies alba", pn.canonicalSpeciesName()); 061 assertEquals("×Abies alba var. alpina (Carl.) Mill., 1887 Döring, nom. illeg. [lost]", pn.fullName()); 062 063 pn.setGenusOrAbove(null); 064 assertEquals("alba alpina", pn.canonicalName()); 065 assertEquals("alba var. alpina", pn.canonicalNameWithMarker()); 066 assertEquals("alba var. alpina (Carl.) Mill., 1887", pn.canonicalNameComplete()); 067 assertNull(pn.canonicalSpeciesName()); 068 assertEquals("alba var. alpina (Carl.) Mill., 1887 Döring, nom. illeg. [lost]", pn.fullName()); 069 } 070 071 @Test 072 public void testTerminalEpithet() { 073 ParsedName pn = new ParsedName(); 074 pn.setGenusOrAbove("Abies"); 075 assertNull(pn.getTerminalEpithet()); 076 077 pn.setInfraSpecificEpithet("abieta"); 078 assertEquals("abieta", pn.getTerminalEpithet()); 079 080 pn.setSpecificEpithet("vulgaris"); 081 assertEquals("abieta", pn.getTerminalEpithet()); 082 083 pn.setInfraSpecificEpithet(null); 084 assertEquals("vulgaris", pn.getTerminalEpithet()); 085 086 pn.setGenusOrAbove(null); 087 assertEquals("vulgaris", pn.getTerminalEpithet()); 088 } 089 090 @Test 091 public void testIndet() { 092 ParsedName pn = new ParsedName(); 093 pn.setType(NameType.SCIENTIFIC); 094 pn.setGenusOrAbove("Abies"); 095 assertFalse(pn.isIndetermined()); 096 097 pn.setRank(Rank.SPECIES); 098 assertTrue(pn.isIndetermined()); 099 100 for (NameType t : NameType.values()) { 101 pn.setType(t); 102 if (t.isParsable()) { 103 assertTrue(pn.isIndetermined()); 104 } else { 105 assertFalse(pn.isIndetermined()); 106 } 107 } 108 pn.setType(NameType.SCIENTIFIC); 109 110 pn.setSpecificEpithet("vulgaris"); 111 assertFalse(pn.isIndetermined()); 112 113 pn.setRank(Rank.SUBSPECIES); 114 assertTrue(pn.isIndetermined()); 115 116 pn.setInfraSpecificEpithet("kingkong"); 117 assertFalse(pn.isIndetermined()); 118 119 for (Rank r : Rank.values()) { 120 if (r.isInfraspecific()) { 121 assertFalse(pn.isIndetermined(), r.toString()); 122 } 123 } 124 125 pn.setInfraSpecificEpithet(null); 126 for (Rank r : Rank.values()) { 127 if (r.isInfraspecific()) { 128 assertTrue(pn.isIndetermined(), r.toString()); 129 } 130 } 131 132 pn.setRank(Rank.SUBGENUS); 133 pn.setSpecificEpithet(null); 134 assertTrue(pn.isIndetermined()); 135 136 pn.setInfraGeneric("Mysubgenus"); 137 assertFalse(pn.isIndetermined()); 138 139 pn = new ParsedName(); 140 pn.setType(NameType.SCIENTIFIC); 141 pn.setRank(Rank.SPECIES_AGGREGATE); 142 pn.setGenusOrAbove("Achillea"); 143 pn.setSpecificEpithet("millefolium"); 144 pn.setAuthorship("L."); 145 assertFalse(pn.isIndetermined()); 146 } 147 148 @Test 149 public void testCanonicalAscii() { 150 ParsedName pn = new ParsedName(); 151 pn.setGenusOrAbove("Abies"); 152 pn.setSpecificEpithet("vülgårîs"); 153 pn.setInfraSpecificEpithet("æbiéñtø"); 154 assertEquals("Abies vulgaris aebiento", pn.canonicalName()); 155 } 156 157 @Test 158 public void testUnparsableCanonical() { 159 ParsedName pn = new ParsedName(); 160 pn.setScientificName("? hostilis Gravenhorst, 1829"); 161 pn.setType(NameType.PLACEHOLDER); 162 assertNull(pn.canonicalName()); 163 } 164 165 /** 166 * http://dev.gbif.org/issues/browse/POR-2624 167 */ 168 @Test 169 public void testSubgenus() { 170 // Brachyhypopomus (Odontohypopomus) Sullivan, Zuanon & Cox Fernandes, 2013 171 ParsedName pn = new ParsedName(); 172 pn.setGenusOrAbove("Brachyhypopomus"); 173 pn.setInfraGeneric("Odontohypopomus"); 174 pn.setAuthorship("Sullivan, Zuanon & Cox Fernandes"); 175 pn.setYear("2013"); 176 assertEquals("Odontohypopomus", pn.canonicalName()); 177 assertEquals("Odontohypopomus", pn.canonicalNameWithMarker()); 178 assertEquals("Brachyhypopomus (Odontohypopomus) Sullivan, Zuanon & Cox Fernandes, 2013", pn.canonicalNameComplete()); 179 // with given rank marker it is shown instead of brackets 180 pn.setRank(Rank.SUBGENUS); 181 assertEquals("Odontohypopomus", pn.canonicalName()); 182 assertEquals("subgen. Odontohypopomus", pn.canonicalNameWithMarker()); 183 assertEquals("Brachyhypopomus subgen. Odontohypopomus Sullivan, Zuanon & Cox Fernandes, 2013", pn.canonicalNameComplete()); 184 185 // Achillea sect. Ptarmica (Mill.) W.D.J.Koch 186 pn = new ParsedName(); 187 pn.setGenusOrAbove("Achillea"); 188 pn.setInfraGeneric("Ptarmica"); 189 pn.setAuthorship("W.D.J.Koch"); 190 pn.setBracketAuthorship("Mill."); 191 192 assertEquals("Ptarmica", pn.canonicalName()); 193 assertEquals("Achillea (Ptarmica) (Mill.) W.D.J.Koch", pn.canonicalNameComplete()); 194 pn.setRank(Rank.SECTION); 195 assertEquals("Achillea sect. Ptarmica (Mill.) W.D.J.Koch", pn.canonicalNameComplete()); 196 } 197 198 @Test 199 public void testBuildName() { 200 ParsedName pn = new ParsedName(); 201 pn.setGenusOrAbove("Pseudomonas"); 202 assertBuildName(pn, "Pseudomonas"); 203 204 pn.setSpecificEpithet("syringae"); 205 assertBuildName(pn, "Pseudomonas syringae"); 206 207 pn.setParsedPartially(true); 208 pn.setAuthorship("Van Hall"); 209 assertBuildName(pn, "Pseudomonas syringae Van Hall", "Pseudomonas syringae", "Pseudomonas syringae Van Hall", "Pseudomonas syringae"); 210 211 pn.setYear("1904"); 212 assertBuildName(pn, "Pseudomonas syringae Van Hall, 1904", "Pseudomonas syringae", "Pseudomonas syringae Van Hall, 1904", "Pseudomonas syringae"); 213 214 pn.setBracketAuthorship("Carl."); 215 assertBuildName(pn, "Pseudomonas syringae (Carl.) Van Hall, 1904", "Pseudomonas syringae", "Pseudomonas syringae (Carl.) Van Hall, 1904", "Pseudomonas syringae"); 216 217 pn.setRank(Rank.PATHOVAR); 218 pn.setInfraSpecificEpithet("aceris"); 219 pn.setBracketAuthorship(null); 220 assertBuildName(pn, "Pseudomonas syringae pv. aceris Van Hall, 1904", "Pseudomonas syringae aceris", "Pseudomonas syringae pv. aceris Van Hall, 1904", "Pseudomonas syringae pv. aceris"); 221 222 pn.setStrain("CFBP 2339"); 223 assertBuildName(pn, "Pseudomonas syringae pv. aceris Van Hall, 1904 CFBP 2339", "Pseudomonas syringae aceris", "Pseudomonas syringae pv. aceris Van Hall, 1904 CFBP 2339", "Pseudomonas syringae pv. aceris CFBP 2339"); 224 225 pn.setYear(null); 226 pn.setAuthorship(null); 227 assertBuildName(pn, "Pseudomonas syringae pv. aceris CFBP 2339", "Pseudomonas syringae aceris", "Pseudomonas syringae pv. aceris CFBP 2339", "Pseudomonas syringae pv. aceris CFBP 2339"); 228 229 pn = new ParsedName(); 230 pn.setGenusOrAbove("Abax"); 231 pn.setSpecificEpithet("carinatus"); 232 pn.setInfraSpecificEpithet("carinatus"); 233 pn.setBracketAuthorship("Duftschmid"); 234 pn.setBracketYear("1812"); 235 pn.setRank(Rank.UNRANKED); 236 assertBuildName(pn, "Abax carinatus carinatus", "Abax carinatus carinatus", "Abax carinatus carinatus", "Abax carinatus carinatus"); 237 238 pn.setRank(null); 239 assertBuildName(pn, "Abax carinatus carinatus", "Abax carinatus carinatus", "Abax carinatus carinatus", "Abax carinatus carinatus"); 240 241 pn.setInfraSpecificEpithet("urinatus"); 242 assertBuildName(pn, "Abax carinatus urinatus (Duftschmid, 1812)", "Abax carinatus urinatus", "Abax carinatus urinatus (Duftschmid, 1812)", "Abax carinatus urinatus"); 243 244 pn.setRank(null); 245 assertBuildName(pn, "Abax carinatus urinatus (Duftschmid, 1812)", "Abax carinatus urinatus", "Abax carinatus urinatus (Duftschmid, 1812)", "Abax carinatus urinatus"); 246 247 pn.setRank(Rank.SUBSPECIES); 248 assertBuildName(pn, "Abax carinatus subsp. urinatus (Duftschmid, 1812)", "Abax carinatus urinatus", "Abax carinatus subsp. urinatus (Duftschmid, 1812)", "Abax carinatus subsp. urinatus"); 249 250 pn = new ParsedName(); 251 pn.setGenusOrAbove("Polypodium"); 252 pn.setSpecificEpithet("vulgare"); 253 pn.setInfraSpecificEpithet("mantoniae"); 254 pn.setBracketAuthorship("Rothm."); 255 pn.setAuthorship("Schidlay"); 256 pn.setRank(Rank.SUBSPECIES); 257 pn.setNotho(NamePart.INFRASPECIFIC); 258 assertBuildName(pn, "Polypodium vulgare nothosubsp. mantoniae (Rothm.) Schidlay", 259 "Polypodium vulgare mantoniae", 260 "Polypodium vulgare nothosubsp. mantoniae (Rothm.) Schidlay", 261 "Polypodium vulgare nothosubsp. mantoniae"); 262 263 pn = new ParsedName(); 264 pn.setGenusOrAbove("Polypodium"); 265 pn.setSpecificEpithet("vulgare"); 266 pn.setInfraSpecificEpithet("mantoniae"); 267 pn.setRank(Rank.INFRASPECIFIC_NAME); 268 assertBuildName(pn, "Polypodium vulgare mantoniae", 269 "Polypodium vulgare mantoniae", 270 "Polypodium vulgare mantoniae", 271 "Polypodium vulgare mantoniae"); 272 273 // unparsable names 274 pn = new ParsedName(); 275 for (NameType t : NameType.values()) { 276 if (!t.isParsable()) { 277 pn.setType(t); 278 pn.setScientificName("SH035824.07FU"); 279 for (Rank r : Rank.values()) { 280 pn.setRank(r); 281 assertBuildName(pn, null, null, null, null); 282 } 283 } 284 } 285 } 286 287 @Test 288 public void testJsonSerde() throws IOException { 289 ParsedName pn = new ParsedName(); 290 pn.setGenusOrAbove("Brachyhypopomus"); 291 pn.setInfraGeneric("Odontohypopomus"); 292 pn.setAuthorship("Sullivan, Zuanon & Cox Fernandes"); 293 pn.setYear("2013"); 294 pn.setRank(Rank.SUBGENUS); 295 SerdeTestUtils.testSerDe(pn, ParsedName.class); 296 297 pn = new ParsedName(); 298 pn.setKey(123); 299 pn.setType(NameType.SCIENTIFIC); 300 pn.setGenusOrAbove("Abax"); 301 pn.setSpecificEpithet("carinatus"); 302 pn.setInfraSpecificEpithet("carinatus"); 303 pn.setBracketAuthorship("Duftschmid"); 304 pn.setBracketYear("1812"); 305 pn.setRank(Rank.INFRASUBSPECIFIC_NAME); 306 SerdeTestUtils.testSerDe(pn, ParsedName.class); 307 308 pn.setAuthorship("Carlos & Kamera"); 309 pn.setYear("1999"); 310 311 for (Rank rank : Rank.values()) { 312 pn.setRank(rank); 313 // UNRANKED intentionally becomes null! 314 if (rank.notOtherOrUnknown()) { 315 String json = SerdeTestUtils.testSerDe(pn, ParsedName.class); 316 assertTrue(json.contains("\"rankMarker\"")); 317 } 318 } 319 // check that rankMarker=null gets removed from json 320 pn.setRank(null); 321 String json = SerdeTestUtils.serialize(pn); 322 assertFalse(json.contains("\"rankMarker\"")); 323 } 324 325 /** 326 * assert all build name methods return the same string 327 * @param name expected string 328 */ 329 private void assertBuildName(ParsedName pn, String name) { 330 assertEquals(name, pn.fullName()); 331 assertEquals(name, pn.canonicalName()); 332 assertEquals(name, pn.canonicalNameComplete()); 333 assertEquals(name, pn.canonicalNameWithMarker()); 334 } 335 336 private void assertBuildName(ParsedName pn, String full, String canonical, String canonicalComplete, String canonicalMarker) { 337 assertEquals(canonical, pn.canonicalName(), "wrong canonicalName"); 338 assertEquals(canonicalMarker, pn.canonicalNameWithMarker(), "wrong canonicalNameWithMarker"); 339 assertEquals(canonicalComplete, pn.canonicalNameComplete(), "wrong canonicalNameComplete"); 340 assertEquals(full, pn.fullName(), "wrong fullName"); 341 } 342}