26 |
26 |
import eu.etaxonomy.cdm.common.CdmUtils;
|
27 |
27 |
import eu.etaxonomy.cdm.io.common.mapping.UndefinedTransformerMethodException;
|
28 |
28 |
import eu.etaxonomy.cdm.io.excel.common.ExcelImporterBase;
|
|
29 |
import eu.etaxonomy.cdm.model.agent.Person;
|
29 |
30 |
import eu.etaxonomy.cdm.model.agent.Team;
|
30 |
31 |
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
|
31 |
32 |
import eu.etaxonomy.cdm.model.common.Annotation;
|
32 |
33 |
import eu.etaxonomy.cdm.model.common.AnnotationType;
|
|
34 |
import eu.etaxonomy.cdm.model.common.CdmBase;
|
|
35 |
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
|
33 |
36 |
import eu.etaxonomy.cdm.model.common.Language;
|
34 |
37 |
import eu.etaxonomy.cdm.model.common.OriginalSourceType;
|
|
38 |
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
|
|
39 |
import eu.etaxonomy.cdm.model.description.DescriptionElementSource;
|
35 |
40 |
import eu.etaxonomy.cdm.model.description.Distribution;
|
36 |
41 |
import eu.etaxonomy.cdm.model.description.Feature;
|
37 |
42 |
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
|
... | ... | |
40 |
45 |
import eu.etaxonomy.cdm.model.description.TextData;
|
41 |
46 |
import eu.etaxonomy.cdm.model.location.NamedArea;
|
42 |
47 |
import eu.etaxonomy.cdm.model.name.BotanicalName;
|
|
48 |
import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
|
|
49 |
import eu.etaxonomy.cdm.model.name.NameRelationship;
|
43 |
50 |
import eu.etaxonomy.cdm.model.name.NameRelationshipType;
|
44 |
51 |
import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
|
45 |
52 |
import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
|
46 |
53 |
import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
|
47 |
54 |
import eu.etaxonomy.cdm.model.name.Rank;
|
|
55 |
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
|
48 |
56 |
import eu.etaxonomy.cdm.model.reference.Reference;
|
49 |
57 |
import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
|
50 |
58 |
import eu.etaxonomy.cdm.model.taxon.Classification;
|
... | ... | |
101 |
109 |
for (PresenceAbsenceTerm status : statuss){
|
102 |
110 |
Distribution distribution = Distribution.NewInstance(cuba, status);
|
103 |
111 |
desc.addElement(distribution);
|
|
112 |
distribution.addSource(makeDescriptionSource(state));
|
104 |
113 |
}
|
105 |
114 |
} catch (UndefinedTransformerMethodException e) {
|
106 |
115 |
e.printStackTrace();
|
... | ... | |
115 |
124 |
* @throws UndefinedTransformerMethodException
|
116 |
125 |
*/
|
117 |
126 |
private List<PresenceAbsenceTerm> makeCubanStatuss(HashMap<String, String> record, CubaImportState state) throws UndefinedTransformerMethodException {
|
118 |
|
boolean isAbsent = false; //TODO
|
119 |
127 |
PresenceAbsenceTerm highestStatus = null;
|
120 |
128 |
|
121 |
129 |
String line = state.getCurrentLine() + ": ";
|
... | ... | |
129 |
137 |
String advStr = getValue(record, "Adv");
|
130 |
138 |
String cultStr = getValue(record, "Cult C");
|
131 |
139 |
|
|
140 |
state.setEndemic(false);
|
|
141 |
|
132 |
142 |
if (endemicStr != null){
|
133 |
143 |
if(endemicStr.equals("+")){
|
134 |
144 |
PresenceAbsenceTerm endemicState = state.getTransformer().getPresenceTermByKey("E");
|
135 |
145 |
result.add(endemicState);
|
136 |
146 |
highestStatus = endemicState;
|
|
147 |
state.setEndemic(true);
|
137 |
148 |
}else if(isMinus(endemicStr)){
|
138 |
149 |
UUID endemicUuid = state.getTransformer().getPresenceTermUuid("-E");
|
139 |
150 |
PresenceAbsenceTerm endemicState = getPresenceTerm(state, endemicUuid, null, null, null, false);
|
... | ... | |
150 |
161 |
}
|
151 |
162 |
if (indigenousStr != null){
|
152 |
163 |
if(indigenousStr.equals("+")){
|
153 |
|
UUID indigenousUuid = state.getTransformer().getPresenceTermUuid("Ind.");
|
154 |
|
PresenceAbsenceTerm indigenousState = getPresenceTerm(state, indigenousUuid, null, null, null, false);
|
|
164 |
PresenceAbsenceTerm indigenousState = state.getTransformer().getPresenceTermByKey("Ind.");
|
|
165 |
// PresenceAbsenceTerm indigenousState = getPresenceTerm(state, indigenousUuid, null, null, null, false);
|
155 |
166 |
result.add(indigenousState);
|
156 |
167 |
highestStatus = highestStatus != null ? highestStatus : indigenousState;
|
157 |
168 |
}else if(isMinus(indigenousStr)){
|
... | ... | |
159 |
170 |
result.add(indigenousState);
|
160 |
171 |
checkAbsentHighestState(highestStatus, line, "indigenous", false);
|
161 |
172 |
}else if(indigenousStr.equals("?")){
|
162 |
|
UUID indigenousDoubtUuid = state.getTransformer().getPresenceTermUuid("?Ind.");
|
163 |
|
PresenceAbsenceTerm indigenousDoubtState = getPresenceTerm(state, indigenousDoubtUuid, null, null, null, false);
|
|
173 |
PresenceAbsenceTerm indigenousDoubtState = state.getTransformer().getPresenceTermByKey("?Ind.");
|
|
174 |
// PresenceAbsenceTerm indigenousDoubtState = getPresenceTerm(state, indigenousDoubtUuid, null, null, null, false);
|
164 |
175 |
result.add(indigenousDoubtState);
|
165 |
176 |
checkAbsentHighestState(highestStatus, line, "indigenous", true);
|
166 |
177 |
}else{
|
... | ... | |
169 |
180 |
}
|
170 |
181 |
if(indigenousDoubtStr != null){
|
171 |
182 |
if(indigenousDoubtStr.equals("D")){
|
172 |
|
UUID indigenousDoubtUuid = state.getTransformer().getPresenceTermUuid("Ind.?");
|
173 |
|
PresenceAbsenceTerm indigenousDoubtState = getPresenceTerm(state, indigenousDoubtUuid, null, null, null, false);
|
174 |
|
result.add(indigenousDoubtState);
|
175 |
|
highestStatus = highestStatus != null ? highestStatus : indigenousDoubtState;
|
|
183 |
PresenceAbsenceTerm doubtIndigenousState = state.getTransformer().getPresenceTermByKey("Ind.?");
|
|
184 |
// PresenceAbsenceTerm doubtIndigenousState = getPresenceTerm(state, doubtIndigenousUuid, null, null, null, false);
|
|
185 |
result.add(doubtIndigenousState);
|
|
186 |
highestStatus = highestStatus != null ? highestStatus : doubtIndigenousState;
|
|
187 |
}else if(isMinus(indigenousDoubtStr)){
|
|
188 |
UUID doubtIndigenousErrorUuid = state.getTransformer().getPresenceTermUuid("-Ind.?");
|
|
189 |
PresenceAbsenceTerm doubtIndigenousErrorState = getPresenceTerm(state, doubtIndigenousErrorUuid, null, null, null, false);
|
|
190 |
result.add(doubtIndigenousErrorState);
|
|
191 |
checkAbsentHighestState(highestStatus, line, "doubtfully indigenous", true);
|
176 |
192 |
}else{
|
177 |
|
logger.warn(line + "Indigenous doubtful not recognized: " + indigenousDoubtStr);
|
|
193 |
logger.warn(line + "doubtfully indigenous not recognized: " + indigenousDoubtStr);
|
178 |
194 |
}
|
179 |
195 |
}
|
180 |
196 |
if(naturalisedStr != null){
|
... | ... | |
218 |
234 |
}
|
219 |
235 |
if(advStr != null){
|
220 |
236 |
if(advStr.equals("A")){
|
221 |
|
UUID advUuid = state.getTransformer().getPresenceTermUuid("Adv.");
|
222 |
|
PresenceAbsenceTerm advState = getPresenceTerm(state, advUuid, null, null, null, false);
|
|
237 |
PresenceAbsenceTerm advState = state.getTransformer().getPresenceTermByKey("Adv.");
|
|
238 |
// PresenceAbsenceTerm advState = getPresenceTerm(state, advUuid, null, null, null, false);
|
223 |
239 |
result.add(advState);
|
224 |
240 |
highestStatus = highestStatus != null ? highestStatus : advState;
|
225 |
241 |
}else if(isMinus(advStr)){
|
... | ... | |
227 |
243 |
PresenceAbsenceTerm advState = getPresenceTerm(state, advUuid, null, null, null, false);
|
228 |
244 |
result.add(advState);
|
229 |
245 |
checkAbsentHighestState(highestStatus, line, "adventive", false);
|
|
246 |
}else if(advStr.equals("(A)")){
|
|
247 |
UUID rareCasualUuid = state.getTransformer().getPresenceTermUuid("(A)");
|
|
248 |
PresenceAbsenceTerm rareCasual = getPresenceTerm(state, rareCasualUuid, null, null, null, false);
|
|
249 |
result.add(rareCasual);
|
230 |
250 |
}else{
|
231 |
251 |
logger.warn(line + "'adventive (casual) alien' not recognized: " + advStr);
|
232 |
252 |
}
|
... | ... | |
263 |
283 |
* @param line
|
264 |
284 |
*/
|
265 |
285 |
private void checkAbsentHighestState(PresenceAbsenceTerm highestStatus, String line, String stateLabel, boolean doubtful) {
|
|
286 |
//can be removed, highest status is not used anymore
|
266 |
287 |
if (highestStatus == null){
|
267 |
288 |
String absentStr = doubtful ? "doubtful" : "absent";
|
268 |
|
logger.warn(line + "Highest cuban state is " + absentStr + " " + stateLabel);
|
|
289 |
logger.info(line + "Highest cuban state is " + absentStr + " " + stateLabel);
|
269 |
290 |
}
|
270 |
291 |
|
271 |
292 |
}
|
... | ... | |
276 |
297 |
* @return
|
277 |
298 |
*/
|
278 |
299 |
private boolean isMinus(String str) {
|
279 |
|
return str.equals("-") || str.equals("–");
|
|
300 |
return str.equals("-") || str.equals("–") || str.equals("‒");
|
280 |
301 |
}
|
281 |
302 |
|
282 |
303 |
|
... | ... | |
315 |
336 |
private static final String heterotypicRegExStr_TEST = "([^\\(]{5,}" +"(\\(.+\\))?" + "[^\\)\\(]{2,})"
|
316 |
337 |
+"(\\((.{6,})\\))?";
|
317 |
338 |
private static final String auctRegExStr = "auct\\."
|
318 |
|
+"((\\sFC(\\-S)?(\\s&\\sA&S)?)|(\\sA&S)|\\sSagra|\\sCombs|\\sBritton|\\sGriseb\\.|\\sWright"
|
|
339 |
+"((\\sFC(\\-S)?(\\s&\\sA&S)?)|(\\sA&S)|\\sSagra|\\sCombs|\\sBritton|\\sGriseb\\.(\\sFC-S|\\sA&S)?|\\sWright"
|
319 |
340 |
+ "|\\sHammer|\\sEngl\\.||\\sMaza|\\sMiers|\\sRoig|\\sBorhidi|\\sFRC|\\sCoL"
|
320 |
341 |
+ "|\\sAckerman|\\sMújica|\\sDíaz|\\sUrb\\.)?(\\s+p\\.\\s*p\\.)?";
|
321 |
342 |
|
... | ... | |
336 |
357 |
* @param state
|
337 |
358 |
* @param taxon
|
338 |
359 |
*/
|
339 |
|
private void makeSynonyms(HashMap<String, String> record, CubaImportState state) {
|
|
360 |
private void makeSynonyms(HashMap<String, String> record, CubaImportState state, boolean isFirstSynonym) {
|
340 |
361 |
// boolean forAccepted = true;
|
341 |
362 |
String synonymStr = record.get("Syn.");
|
342 |
363 |
String line = state.getCurrentLine() + ": ";
|
343 |
364 |
|
|
365 |
|
344 |
366 |
if (synonymStr == null){
|
345 |
367 |
//TODO test that this is not a synonym only line
|
346 |
368 |
return;
|
347 |
369 |
}
|
|
370 |
|
|
371 |
if (state.getCurrentTaxon() == null){
|
|
372 |
logger.error(line + "Current taxon is null for synonym");
|
|
373 |
return;
|
|
374 |
}
|
|
375 |
|
|
376 |
|
348 |
377 |
synonymStr = synonymStr.trim();
|
|
378 |
synonymStr = synonymStr.replace("[taxon]", "[infraspec.]");
|
349 |
379 |
|
350 |
380 |
// String heterotypicRegExStr = "([^\\(]{5,}(\\(.+\\))?[^\\)\\(]{2,})(\\((.{6,})\\))?";
|
351 |
381 |
// String heterotypicRegExStr = "([^\\(]{5,})(\\((.{6,})\\))?";
|
352 |
382 |
|
353 |
383 |
// Pattern heterotypicRegEx = Pattern.compile(heterotypicRegExStr + homonymRegExStr);
|
354 |
384 |
|
|
385 |
|
355 |
386 |
Matcher missapliedMatcher = missapliedRegEx.matcher(synonymStr);
|
356 |
387 |
Matcher nomInvalMatcher = nomInvalRegEx.matcher(synonymStr);
|
357 |
388 |
Matcher acceptedMatcher = acceptedRegEx.matcher(synonymStr);
|
... | ... | |
363 |
394 |
boolean doubtful = missapliedMatcher.group(1) != null;
|
364 |
395 |
String firstPart = missapliedMatcher.group(2);
|
365 |
396 |
BotanicalName name = (BotanicalName)nameParser.parseSimpleName(firstPart, state.getConfig().getNomenclaturalCode(), Rank.SPECIES());
|
|
397 |
name.addSource(makeOriginalSource(state));
|
366 |
398 |
|
367 |
399 |
String secondPart = missapliedMatcher.group(3);
|
368 |
400 |
Taxon misappliedNameTaxon = Taxon.NewInstance(name, null);
|
|
401 |
misappliedNameTaxon.addSource(makeOriginalSource(state));
|
369 |
402 |
misappliedNameTaxon.setDoubtful(doubtful);
|
370 |
403 |
if (secondPart.startsWith("sensu")){
|
371 |
404 |
secondPart = secondPart.substring(5).trim();
|
... | ... | |
392 |
425 |
logger.warn(state.getCurrentLine() + ": After inval to be implemented: " + afterInval);
|
393 |
426 |
}
|
394 |
427 |
BotanicalName name = (BotanicalName)nameParser.parseSimpleName(firstPart, state.getConfig().getNomenclaturalCode(), Rank.SPECIES());
|
|
428 |
name.addSource(makeOriginalSource(state));
|
395 |
429 |
NomenclaturalStatus status = NomenclaturalStatus.NewInstance( NomenclaturalStatusType.INVALID());
|
396 |
430 |
name.addStatus(status);
|
397 |
|
state.getCurrentTaxon().addSynonymName(name, SynonymRelationshipType.SYNONYM_OF());
|
|
431 |
SynonymRelationship sr = state.getCurrentTaxon().addSynonymName(name, SynonymRelationshipType.SYNONYM_OF());
|
|
432 |
sr.getSynonym().addSource(makeOriginalSource(state));
|
398 |
433 |
}else if (sphalmMatcher.matches()){
|
399 |
434 |
String firstPart = sphalmMatcher.group(1);
|
400 |
435 |
String sphalmPart = synonymStr.replace(firstPart, "").replace("“","").replace("”","").trim();
|
401 |
436 |
BotanicalName name = (BotanicalName)nameParser.parseSimpleName(firstPart, state.getConfig().getNomenclaturalCode(), Rank.SPECIES());
|
402 |
437 |
// NomenclaturalStatus status = NomenclaturalStatus.NewInstance( NomenclaturalStatusType.INVALID());
|
403 |
438 |
// name.addStatus(status);
|
|
439 |
name.addSource(makeOriginalSource(state));
|
404 |
440 |
SynonymRelationship sr = state.getCurrentTaxon().addSynonymName(name, SynonymRelationshipType.SYNONYM_OF());
|
405 |
441 |
sr.getSynonym().setAppendedPhrase(sphalmPart);
|
406 |
442 |
sr.getSynonym().setSec(null);
|
|
443 |
sr.getSynonym().addSource(makeOriginalSource(state));
|
407 |
444 |
}else if (acceptedMatcher.matches()){
|
408 |
445 |
String firstPart = acceptedMatcher.group(1);
|
409 |
446 |
String homonymPart = acceptedMatcher.groupCount() < 2 ? null : acceptedMatcher.group(2);
|
410 |
|
handleHomotypicGroup(firstPart, state, (BotanicalName)state.getCurrentTaxon().getName(), false, homonyms, homonymPart, false);
|
|
447 |
List<BotanicalName> list = handleHomotypicGroup(firstPart, state, (BotanicalName)state.getCurrentTaxon().getName(), false, homonyms, homonymPart, false);
|
|
448 |
checkFirstSynonym(state, list, isFirstSynonym, synonymStr, false);
|
411 |
449 |
}else if(heterotypicMatcher.matches()){
|
412 |
450 |
String firstPart = heterotypicMatcher.group(1).trim();
|
413 |
451 |
String secondPart = heterotypicMatcher.groupCount() < 3 ? null : heterotypicMatcher.group(3);
|
... | ... | |
415 |
453 |
boolean isDoubtful = firstPart.matches("^\\?\\s*.*");
|
416 |
454 |
firstPart = replaceHomonIlleg(firstPart);
|
417 |
455 |
boolean isHomonym = firstPart.matches(".*" + HOMONYM_MARKER);
|
418 |
|
BotanicalName synName = makeName(firstPart);
|
|
456 |
BotanicalName synName = makeName(state, firstPart);
|
419 |
457 |
if (synName.isProtectedTitleCache()){
|
420 |
|
logger.warn(line + " heterotypic base synonym could not be parsed correctly:" + firstPart);
|
|
458 |
logger.warn(line + "Heterotypic base synonym could not be parsed correctly: " + firstPart);
|
421 |
459 |
}
|
422 |
460 |
if (isHomonym){
|
423 |
461 |
homonyms.add(synName);
|
424 |
462 |
}
|
425 |
463 |
SynonymRelationship sr = state.getCurrentTaxon().addHeterotypicSynonymName(synName);
|
426 |
464 |
sr.getSynonym().setDoubtful(isDoubtful);
|
427 |
|
handleHomotypicGroup(secondPart, state, synName, true, homonyms, homonymPart, isDoubtful);
|
|
465 |
sr.getSynonym().addSource(makeOriginalSource(state));
|
|
466 |
List<BotanicalName> list = handleHomotypicGroup(secondPart, state, synName, true, homonyms, homonymPart, isDoubtful);
|
|
467 |
checkFirstSynonym(state, list, isFirstSynonym, synonymStr, true);
|
|
468 |
|
|
469 |
}else if (isSpecialHeterotypic(synonymStr)){
|
|
470 |
BotanicalName synName = makeName(state, synonymStr);
|
|
471 |
if (synName.isProtectedTitleCache()){
|
|
472 |
logger.warn(line + "Special heterotypic synonym could not be parsed correctly:" + synonymStr);
|
|
473 |
}
|
|
474 |
SynonymRelationship sr = state.getCurrentTaxon().addHeterotypicSynonymName(synName);
|
|
475 |
sr.getSynonym().addSource(makeOriginalSource(state));
|
428 |
476 |
}else{
|
429 |
477 |
logger.warn(line + "Synonym entry does not match: " + synonymStr);
|
430 |
478 |
}
|
431 |
479 |
}
|
432 |
480 |
|
|
481 |
/**
|
|
482 |
* @param state
|
|
483 |
* @param list
|
|
484 |
* @param isFirstSynonym
|
|
485 |
* @param synonymStr
|
|
486 |
* @param b
|
|
487 |
*/
|
|
488 |
private void checkFirstSynonym(CubaImportState state, List<BotanicalName> list, boolean isFirstSynonym, String synonymStr, boolean isHeterotypicMatcher) {
|
|
489 |
if (!isFirstSynonym){
|
|
490 |
return;
|
|
491 |
}
|
|
492 |
String line = state.getCurrentLine() + ": ";
|
|
493 |
BotanicalName currentName = isHeterotypicMatcher? (BotanicalName)state.getCurrentTaxon().getName(): list.get(0);
|
|
494 |
boolean currentHasBasionym = currentName.getBasionymAuthorship() != null;
|
|
495 |
BotanicalName firstSynonym = isHeterotypicMatcher ? list.get(0): list.get(1);
|
|
496 |
// if (list.size() <= 1){
|
|
497 |
// logger.error(line + "homotypic list size is 1 but shouldn't");
|
|
498 |
// return;
|
|
499 |
// }
|
|
500 |
if (isHeterotypicMatcher && currentHasBasionym){
|
|
501 |
logger.error(line + "Current taxon (" + currentName.getTitleCache() + ") has basionym author but has no homotypic basionym , but : " + synonymStr);
|
|
502 |
}else if (isHeterotypicMatcher){
|
|
503 |
//first synonym must not have a basionym author
|
|
504 |
if (firstSynonym.getBasionymAuthorship() != null){
|
|
505 |
logger.error(line + "Current taxon (" + currentName.getTitleCache() + ") has no basionym but first synonym requires basionym : " + synonymStr);
|
|
506 |
}
|
|
507 |
}else{ //isAcceptedMatcher
|
|
508 |
if (currentHasBasionym){
|
|
509 |
if (! matchAuthor(currentName.getBasionymAuthorship(), firstSynonym.getCombinationAuthorship())){
|
|
510 |
logger.info(line + "Current basionym author and first synonym combination author do not match: " + currentName.getTitleCache() + "<->" + firstSynonym.getTitleCache());
|
|
511 |
}
|
|
512 |
}else{
|
|
513 |
if (! matchAuthor(currentName.getCombinationAuthorship(), firstSynonym.getBasionymAuthorship())){
|
|
514 |
logger.info(line + "Current combination author and first synonym basionym author do not match: " + currentName.getTitleCache() + "<->" + firstSynonym.getTitleCache());
|
|
515 |
}
|
|
516 |
}
|
|
517 |
}
|
|
518 |
|
|
519 |
}
|
|
520 |
|
|
521 |
|
|
522 |
/**
|
|
523 |
* @param synonymStr
|
|
524 |
* @return
|
|
525 |
*/
|
|
526 |
private boolean isSpecialHeterotypic(String synonymStr) {
|
|
527 |
if (synonymStr == null){
|
|
528 |
return false;
|
|
529 |
}else if (synonymStr.equals("Rhynchospora prenleloupiana (‘prenteloupiana’) Boeckeler")){
|
|
530 |
return true;
|
|
531 |
}else if (synonymStr.equals("Psidium longipes var. orbiculare (O.Berg) McVaugh")){
|
|
532 |
return true;
|
|
533 |
}
|
|
534 |
return false;
|
|
535 |
}
|
|
536 |
|
|
537 |
|
|
538 |
/**
|
|
539 |
* @param areaKey
|
|
540 |
* @param record
|
|
541 |
* @param state
|
|
542 |
* @param taxon
|
|
543 |
*/
|
|
544 |
private void makeSingleProvinceDistribution(String areaKey,
|
|
545 |
HashMap<String, String> record,
|
|
546 |
CubaImportState state) {
|
|
547 |
try {
|
|
548 |
UUID areaUuid = state.getTransformer().getNamedAreaUuid(areaKey);
|
|
549 |
if (areaUuid == null){
|
|
550 |
logger.warn("Area not recognized: " + areaKey);
|
|
551 |
return;
|
|
552 |
}
|
|
553 |
if (record.get(areaKey)==null){
|
|
554 |
return; //no status defined
|
|
555 |
}
|
|
556 |
|
|
557 |
NamedArea area = getNamedArea(state, areaUuid, null, null, null, null, null);
|
|
558 |
if (area == null){
|
|
559 |
logger.warn(state.getCurrentLine() + ": Area not recognized: " + area);
|
|
560 |
}
|
|
561 |
TaxonDescription desc = getTaxonDescription(state.getCurrentTaxon(), false, true);
|
|
562 |
PresenceAbsenceTerm status = makeProvinceStatus(areaKey, record, state);
|
|
563 |
if (status == null){
|
|
564 |
logger.warn(state.getCurrentLine() + ": Province distribution status could not be defined: " + record.get(areaKey));
|
|
565 |
}
|
|
566 |
Distribution distribution = Distribution.NewInstance(area, status);
|
|
567 |
desc.addElement(distribution);
|
|
568 |
distribution.addSource(makeDescriptionSource(state));
|
|
569 |
} catch (UndefinedTransformerMethodException e) {
|
|
570 |
e.printStackTrace();
|
|
571 |
}
|
|
572 |
|
|
573 |
}
|
433 |
574 |
|
434 |
575 |
|
435 |
576 |
/**
|
... | ... | |
441 |
582 |
* @param taxon
|
442 |
583 |
* @param homotypicalGroup
|
443 |
584 |
*/
|
444 |
|
private void handleHomotypicGroup(String homotypicStr,
|
|
585 |
private List<BotanicalName> handleHomotypicGroup(String homotypicStrOrig,
|
445 |
586 |
CubaImportState state,
|
446 |
587 |
BotanicalName homotypicName,
|
447 |
588 |
boolean isHeterotypic,
|
... | ... | |
449 |
590 |
String homonymPart,
|
450 |
591 |
boolean isDoubtful) {
|
451 |
592 |
|
|
593 |
List<BotanicalName> homotypicNameList = new ArrayList<>();
|
|
594 |
homotypicNameList.add(homotypicName);
|
|
595 |
|
|
596 |
String homotypicStr = homotypicStrOrig;
|
452 |
597 |
if (homotypicStr == null){
|
453 |
|
return;
|
|
598 |
return homotypicNameList;
|
454 |
599 |
}else if (homotypicStr.startsWith("(") && homotypicStr.endsWith("")){
|
455 |
600 |
homotypicStr = homotypicStr.substring(1, homotypicStr.length() - 1);
|
456 |
601 |
}
|
457 |
602 |
|
458 |
|
BotanicalName currentBasionym = homotypicName;
|
|
603 |
HomotypicalGroup homotypicGroup = homotypicName.getHomotypicalGroup();
|
459 |
604 |
String[] splits = homotypicStr.split("\\s*,\\s*");
|
460 |
605 |
for (String split : splits){
|
461 |
606 |
split = replaceHomonIlleg(split);
|
462 |
607 |
boolean isHomonym = split.matches(".*" + HOMONYM_MARKER);
|
463 |
|
BotanicalName newName = makeName(split);
|
|
608 |
BotanicalName newName = makeName(state, split);
|
|
609 |
newName.setHomotypicalGroup(homotypicGroup); //not really necessary as this is later set anyway
|
464 |
610 |
if (newName.isProtectedTitleCache()){
|
465 |
611 |
logger.warn(state.getCurrentLine() + ": homotypic name part could not be parsed: " + split);
|
466 |
612 |
}
|
... | ... | |
468 |
614 |
homonyms.add(newName);
|
469 |
615 |
}
|
470 |
616 |
if (isHeterotypic){
|
471 |
|
SynonymRelationship sr = state.getCurrentTaxon().addHeterotypicSynonymName(newName, homotypicName.getHomotypicalGroup(), null, null);
|
|
617 |
SynonymRelationship sr = state.getCurrentTaxon().addHeterotypicSynonymName(newName, homotypicGroup, null, null);
|
472 |
618 |
sr.getSynonym().setDoubtful(isDoubtful);
|
|
619 |
sr.getSynonym().addSource(makeOriginalSource(state));
|
473 |
620 |
// newName.addBasionym(homotypicName);
|
474 |
|
currentBasionym = handleBasionym(currentBasionym, newName);
|
475 |
621 |
}else{
|
476 |
622 |
state.getCurrentTaxon().addHomotypicSynonymName(newName, null, null);
|
477 |
|
handleBasionym(currentBasionym, newName);
|
478 |
623 |
}
|
|
624 |
handleBasionym(state, homotypicNameList, homonyms, newName);
|
|
625 |
homotypicNameList.add(newName);
|
479 |
626 |
}
|
480 |
|
makeHomonyms(homonyms, homonymPart, state, currentBasionym);
|
|
627 |
makeHomonyms(homonyms, homonymPart, state, homotypicGroup);
|
|
628 |
return homotypicNameList;
|
481 |
629 |
}
|
482 |
630 |
|
483 |
631 |
|
... | ... | |
498 |
646 |
* @param currentBasionym
|
499 |
647 |
*/
|
500 |
648 |
private void makeHomonyms(List<BotanicalName> homonyms, String homonymPartOrig, CubaImportState state,
|
501 |
|
BotanicalName currentBasionym) {
|
|
649 |
HomotypicalGroup homotypicGroup) {
|
502 |
650 |
String line = state.getCurrentLine() + ": ";
|
503 |
651 |
String homonymPart = homonymPartOrig == null ? "" : homonymPartOrig.trim();
|
504 |
652 |
if (homonyms.isEmpty() && homonymPart.equals("")){
|
... | ... | |
511 |
659 |
String[] splits = homonymPart.split("\\]\\s*\\[");
|
512 |
660 |
if (splits.length != homonyms.size()){
|
513 |
661 |
if(homonyms.size() == 0 && splits.length >= 1){
|
514 |
|
handleSimpleBlockingNames(splits, state, currentBasionym);
|
|
662 |
handleSimpleBlockingNames(splits, state, homotypicGroup);
|
515 |
663 |
}else{
|
516 |
664 |
logger.warn(line + "Number of homonyms (" + homonyms.size() + ") and homonymParts ("+splits.length+") does not match");
|
517 |
665 |
}
|
... | ... | |
520 |
668 |
int i = 0;
|
521 |
669 |
for (String split : splits){
|
522 |
670 |
split = split.replaceAll("^non\\s+", "");
|
523 |
|
BotanicalName newName = makeName(split);
|
|
671 |
BotanicalName newName = makeName(state, split);
|
524 |
672 |
// BotanicalName newName = (BotanicalName)nameParser.parseReferencedName(split, state.getConfig().getNomenclaturalCode(), Rank.SPECIES());
|
525 |
673 |
if (newName.isProtectedTitleCache()){
|
526 |
674 |
logger.warn(state.getCurrentLine() + ": homonym name could not be parsed: " + split);
|
527 |
675 |
}
|
528 |
|
newName.addRelationshipToName(homonyms.get(i), NameRelationshipType.LATER_HOMONYM(), null);
|
|
676 |
homonyms.get(i).addRelationshipToName(newName, NameRelationshipType.LATER_HOMONYM(), null);
|
529 |
677 |
i++;
|
530 |
678 |
}
|
531 |
679 |
}
|
532 |
680 |
|
533 |
|
|
534 |
681 |
/**
|
535 |
682 |
* @param homonymPart
|
536 |
683 |
* @param state
|
537 |
|
* @param currentBasionym
|
|
684 |
* @param homotypicGroup
|
538 |
685 |
*/
|
539 |
|
private void handleSimpleBlockingNames(String[] splitsi, CubaImportState state,
|
540 |
|
BotanicalName currentBasionym) {
|
|
686 |
private void handleSimpleBlockingNames(String[] splitsi,
|
|
687 |
CubaImportState state,
|
|
688 |
HomotypicalGroup homotypicGroup) {
|
|
689 |
List<BotanicalName> replacementNameCandidates = new ArrayList<>();
|
541 |
690 |
for (String spliti : splitsi){
|
542 |
691 |
|
543 |
692 |
String split = spliti.replaceAll("^non\\s+", "");
|
544 |
|
BotanicalName newName = makeName(split);
|
|
693 |
BotanicalName newName = makeName(state, split);
|
545 |
694 |
if (newName.isProtectedTitleCache()){
|
546 |
695 |
logger.warn(state.getCurrentLine() + ": blocking name could not be parsed: " + split);
|
547 |
696 |
}
|
548 |
|
Set<BotanicalName> typifiedNames = (Set)currentBasionym.getHomotypicalGroup().getTypifiedNames();
|
|
697 |
Set<BotanicalName> typifiedNames = (Set)homotypicGroup.getTypifiedNames();
|
549 |
698 |
Set<BotanicalName> candidates = new HashSet<>();
|
550 |
699 |
for (BotanicalName name : typifiedNames){
|
551 |
700 |
if (name.getGenusOrUninomial() != null && name.getGenusOrUninomial().equals(newName.getGenusOrUninomial())){
|
... | ... | |
555 |
704 |
}
|
556 |
705 |
}
|
557 |
706 |
if (candidates.size() == 1){
|
558 |
|
newName.addRelationshipToName(candidates.iterator().next(), NameRelationshipType.BLOCKING_NAME_FOR(), null);
|
|
707 |
BotanicalName blockedName = candidates.iterator().next();
|
|
708 |
newName.addRelationshipToName(blockedName, NameRelationshipType.BLOCKING_NAME_FOR(), null);
|
|
709 |
replacementNameCandidates.add(blockedName);
|
559 |
710 |
}else{
|
560 |
711 |
logger.warn(state.getCurrentLine() + ": Blocking name could not be handled. " + candidates.size() + " candidates.");
|
561 |
712 |
}
|
562 |
713 |
}
|
|
714 |
makeReplacedSynonymIfPossible(state, homotypicGroup, replacementNameCandidates);
|
|
715 |
}
|
|
716 |
|
|
717 |
/**
|
|
718 |
* @param homotypicGroup
|
|
719 |
* @param replacementNameCandidates
|
|
720 |
*/
|
|
721 |
private void makeReplacedSynonymIfPossible(CubaImportState state,
|
|
722 |
HomotypicalGroup homotypicGroup,
|
|
723 |
List<BotanicalName> replacementNameCandidates) {
|
|
724 |
String line = state.getCurrentLine() +": ";
|
|
725 |
List<BotanicalName> replacedCandidates = new ArrayList<>();
|
|
726 |
for (TaxonNameBase<?, ?> typifiedName : homotypicGroup.getTypifiedNames()){
|
|
727 |
BotanicalName candidate = (BotanicalName)typifiedName;
|
|
728 |
if (candidate.getBasionymAuthorship() == null){
|
|
729 |
if (candidate.getStatus().isEmpty()){
|
|
730 |
if (! replacementNameCandidates.contains(candidate)){
|
|
731 |
replacedCandidates.add(candidate);
|
|
732 |
}
|
|
733 |
}
|
|
734 |
}
|
|
735 |
}
|
|
736 |
if (replacedCandidates.size() == 1){
|
|
737 |
BotanicalName replacedSynonym = replacedCandidates.iterator().next();
|
|
738 |
for (BotanicalName replacementName : replacementNameCandidates){
|
|
739 |
replacementName.addReplacedSynonym(replacedSynonym, null, null, null);
|
|
740 |
}
|
|
741 |
}else if (replacedCandidates.size() < 1){
|
|
742 |
logger.warn(line + "No replaced synonym candidate found");
|
|
743 |
}else{
|
|
744 |
logger.warn(line + "More than 1 ("+replacedCandidates.size()+") replaced synonym candidates found");
|
|
745 |
}
|
563 |
746 |
}
|
564 |
747 |
|
565 |
748 |
|
566 |
749 |
/**
|
|
750 |
* @param homotypicGroup
|
567 |
751 |
* @param newName
|
568 |
|
* @param homotypicName
|
|
752 |
*/
|
|
753 |
private void handleBasionym(CubaImportState state, List<BotanicalName> homotypicNameList,
|
|
754 |
List<BotanicalName> homonyms, BotanicalName newName) {
|
|
755 |
for (BotanicalName existingName : homotypicNameList){
|
|
756 |
if (existingName != newName){ //should not happen anymore, as new name is added later
|
|
757 |
boolean onlyIfNotYetExists = true;
|
|
758 |
createBasionymRelationIfPossible(state, existingName, newName, homonyms.contains(newName), onlyIfNotYetExists);
|
|
759 |
}
|
|
760 |
}
|
|
761 |
}
|
|
762 |
|
|
763 |
/**
|
|
764 |
* @param state
|
|
765 |
* @param name1
|
|
766 |
* @param name2
|
569 |
767 |
* @return
|
570 |
768 |
*/
|
571 |
|
private BotanicalName handleBasionym(BotanicalName currentBasionym, BotanicalName name2) {
|
572 |
|
BotanicalName basionymName = currentBasionym;
|
|
769 |
private void createBasionymRelationIfPossible(CubaImportState state, BotanicalName name1, BotanicalName name2,
|
|
770 |
boolean name2isHomonym, boolean onlyIfNotYetExists) {
|
|
771 |
BotanicalName basionymName = name1;
|
573 |
772 |
BotanicalName newCombination = name2;
|
574 |
|
//switch if necessary
|
575 |
|
if (basionymName.getBasionymAuthorship() != null && newCombination.getBasionymAuthorship() == null){
|
|
773 |
//exactly one name must have a basionym author
|
|
774 |
if (name1.getBasionymAuthorship() == null && name2.getBasionymAuthorship() == null
|
|
775 |
|| name1.getBasionymAuthorship() != null && name2.getBasionymAuthorship() != null){
|
|
776 |
return;
|
|
777 |
}
|
|
778 |
|
|
779 |
//switch order if necessary
|
|
780 |
if (! name2isHomonym && basionymName.getBasionymAuthorship() != null && newCombination.getBasionymAuthorship() == null){
|
576 |
781 |
basionymName = name2;
|
577 |
|
newCombination = currentBasionym;
|
|
782 |
newCombination = name1;
|
|
783 |
}
|
|
784 |
if (matchAuthor(basionymName.getCombinationAuthorship(), newCombination.getBasionymAuthorship())
|
|
785 |
&& matchLastNamePart(basionymName, newCombination)){
|
|
786 |
newCombination.addBasionym(basionymName);
|
|
787 |
}else{
|
|
788 |
if ( (newCombination.getBasionyms().isEmpty() || ! onlyIfNotYetExists)
|
|
789 |
&& isLegitimate(basionymName)
|
|
790 |
&& ! name2isHomonym){
|
|
791 |
logger.info(state.getCurrentLine() + ": Names are potential basionyms but either author or name part do not match: " + basionymName.getTitleCache() + " <-> " + newCombination.getTitleCache());
|
|
792 |
}
|
578 |
793 |
}
|
579 |
|
// newCombination.getHomotypicalGroup().removeGroupBasionym(xxx);
|
580 |
|
if (matchAuthor(basionymName.getCombinationAuthorship(), newCombination.getBasionymAuthorship())){
|
581 |
|
newCombination.getHomotypicalGroup().setGroupBasionym(basionymName);
|
|
794 |
}
|
|
795 |
|
|
796 |
/**
|
|
797 |
* @param basionymName
|
|
798 |
* @return
|
|
799 |
*/
|
|
800 |
private boolean isLegitimate(BotanicalName basionymName) {
|
|
801 |
for (NomenclaturalStatus nomStatus : basionymName.getStatus()){
|
|
802 |
if (nomStatus.getType()!= null && nomStatus.getType().isIllegitimateType()){
|
|
803 |
return false;
|
|
804 |
}
|
|
805 |
}
|
|
806 |
for (NameRelationship nameRel : basionymName.getNameRelations()){
|
|
807 |
if (nameRel.getType()!= null && nameRel.getType().isIllegitimateType()){
|
|
808 |
return false;
|
|
809 |
}
|
582 |
810 |
}
|
583 |
|
return basionymName;
|
|
811 |
return true;
|
|
812 |
}
|
|
813 |
|
|
814 |
|
|
815 |
/**
|
|
816 |
* @param basionymName
|
|
817 |
* @param newCombination
|
|
818 |
* @return
|
|
819 |
*/
|
|
820 |
private boolean matchLastNamePart(BotanicalName name1, BotanicalName name2) {
|
|
821 |
String lastNamePart1 = name1.getLastNamePart();
|
|
822 |
String lastNamePart2 = name2.getLastNamePart();
|
|
823 |
if (lastNamePart1 != null && lastNamePart2 != null){
|
|
824 |
lastNamePart1 = normalizeBasionymNamePart(lastNamePart1);
|
|
825 |
lastNamePart2 = normalizeBasionymNamePart(lastNamePart2);
|
|
826 |
return (lastNamePart1.equals(lastNamePart2));
|
|
827 |
}else{
|
|
828 |
return false;
|
|
829 |
}
|
|
830 |
}
|
|
831 |
|
|
832 |
/**
|
|
833 |
* @param lastNamePart1
|
|
834 |
* @return
|
|
835 |
*/
|
|
836 |
private String normalizeBasionymNamePart(String lastNamePart) {
|
|
837 |
String namePart = lastNamePart.toLowerCase()
|
|
838 |
.replaceAll("(um|us|a|is|e|os|on|or)$", "")
|
|
839 |
.replaceAll("er$", "r") //e.g. ruber <-> rubra
|
|
840 |
.replaceAll("ese$", "s"); //e.g. cayanensis <-> cayanenese
|
|
841 |
//TODO tampensis / tampense
|
|
842 |
return namePart;
|
584 |
843 |
}
|
585 |
844 |
|
586 |
845 |
|
... | ... | |
627 |
886 |
if (taxonStr == null){
|
628 |
887 |
return isSynonym ? state.getCurrentTaxon() : null;
|
629 |
888 |
}
|
|
889 |
|
630 |
890 |
boolean isAbsent = false;
|
631 |
891 |
if (taxonStr.startsWith("[") && taxonStr.endsWith("]")){
|
632 |
892 |
taxonStr = taxonStr.substring(1, taxonStr.length() - 1);
|
633 |
893 |
isAbsent = true;
|
634 |
894 |
}
|
635 |
895 |
|
636 |
|
BotanicalName botanicalName = makeName(taxonStr);
|
|
896 |
boolean isAuct = false;
|
|
897 |
if (taxonStr.endsWith("auct.")){
|
|
898 |
isAuct = true;
|
|
899 |
taxonStr.replace("auct.", "").trim();
|
|
900 |
}
|
|
901 |
state.setTaxonIsAbsent(isAbsent);
|
|
902 |
BotanicalName botanicalName = makeName(state, taxonStr);
|
637 |
903 |
Reference<?> sec = getSecReference(state);
|
638 |
904 |
Taxon taxon = Taxon.NewInstance(botanicalName, sec);
|
|
905 |
if (isAuct){
|
|
906 |
taxon.setAppendedPhrase("auct.");
|
|
907 |
}
|
|
908 |
|
639 |
909 |
TaxonNode higherNode;
|
640 |
910 |
if (botanicalName.isProtectedTitleCache()){
|
641 |
911 |
logger.warn(state.getCurrentLine() + ": Taxon could not be parsed: " + taxonStr);
|
... | ... | |
647 |
917 |
higherNode = genus.getTaxonNodes().iterator().next();
|
648 |
918 |
}else{
|
649 |
919 |
BotanicalName name = BotanicalName.NewInstance(Rank.GENUS());
|
|
920 |
name.addSource(makeOriginalSource(state));
|
650 |
921 |
name.setGenusOrUninomial(genusStr);
|
651 |
922 |
genus = Taxon.NewInstance(name, sec);
|
|
923 |
genus.addSource(makeOriginalSource(state));
|
652 |
924 |
higherNode = familyNode.addChildTaxon(genus, null, null);
|
653 |
925 |
state.putHigherTaxon(genusStr, genus);
|
654 |
926 |
}
|
655 |
927 |
}
|
656 |
928 |
|
657 |
929 |
higherNode.addChildTaxon(taxon, null, null);
|
|
930 |
taxon.addSource(makeOriginalSource(state));
|
658 |
931 |
|
659 |
932 |
return taxon;
|
660 |
933 |
}
|
... | ... | |
665 |
938 |
* @param taxonStr
|
666 |
939 |
* @return
|
667 |
940 |
*/
|
668 |
|
private BotanicalName makeName(String nameStrOrig) {
|
|
941 |
private BotanicalName makeName(CubaImportState state, String nameStrOrig) {
|
669 |
942 |
//normalize
|
670 |
943 |
String nameStr = normalizeStatus(nameStrOrig);
|
671 |
944 |
//orthVar
|
... | ... | |
675 |
948 |
orthVar = orthVarMatcher.group(1);
|
676 |
949 |
nameStr = nameStr.replace(" " + orthVar, "").trim().replaceAll("\\s{2,}", " ");
|
677 |
950 |
orthVar = orthVar.substring(2, orthVar.length() - 2);
|
|
951 |
}
|
678 |
952 |
|
|
953 |
boolean isNomInval = false;
|
|
954 |
if (nameStr.endsWith("nom. inval.")){
|
|
955 |
isNomInval = true;
|
|
956 |
nameStr = nameStr.replace("nom. inval.", "").trim();
|
679 |
957 |
}
|
|
958 |
|
680 |
959 |
BotanicalName result = (BotanicalName)nameParser.parseReferencedName(nameStr, nc, Rank.SPECIES());
|
|
960 |
result.addSource(makeOriginalSource(state));
|
|
961 |
if (isNomInval){
|
|
962 |
result.addStatus(NomenclaturalStatus.NewInstance(NomenclaturalStatusType.INVALID()));
|
|
963 |
}
|
681 |
964 |
if (orthVar != null){
|
682 |
965 |
BotanicalName orthVarName = (BotanicalName)result.clone();
|
|
966 |
orthVarName.addSource(makeOriginalSource(state));
|
683 |
967 |
//TODO
|
684 |
968 |
Reference<?> citation = null;
|
685 |
969 |
orthVarName.addRelationshipToName(result, NameRelationshipType.ORTHOGRAPHIC_VARIANT(), citation, null, null);
|
686 |
970 |
orthVarName.setSpecificEpithet(orthVar);
|
687 |
971 |
}
|
|
972 |
normalizeAuthors(result);
|
688 |
973 |
return result;
|
689 |
974 |
|
690 |
975 |
}
|
691 |
976 |
|
|
977 |
/**
|
|
978 |
* @param result
|
|
979 |
*/
|
|
980 |
private void normalizeAuthors(BotanicalName result) {
|
|
981 |
result.setCombinationAuthorship(normalizeAuthor(result.getCombinationAuthorship()));
|
|
982 |
result.setExCombinationAuthorship(normalizeAuthor(result.getExCombinationAuthorship()));
|
|
983 |
result.setExBasionymAuthorship(normalizeAuthor(result.getExBasionymAuthorship()));
|
|
984 |
result.setBasionymAuthorship(normalizeAuthor(result.getBasionymAuthorship()));
|
|
985 |
|
|
986 |
}
|
|
987 |
|
|
988 |
|
|
989 |
/**
|
|
990 |
* @param combinationAuthorship
|
|
991 |
* @return
|
|
992 |
*/
|
|
993 |
private TeamOrPersonBase<?> normalizeAuthor(TeamOrPersonBase<?> author) {
|
|
994 |
if (author == null){
|
|
995 |
return null;
|
|
996 |
}
|
|
997 |
TeamOrPersonBase<?> result;
|
|
998 |
if (author.isInstanceOf(Person.class)){
|
|
999 |
result = normalizePerson(CdmBase.deproxy(author, Person.class));
|
|
1000 |
}else{
|
|
1001 |
Team team = CdmBase.deproxy(author, Team.class);
|
|
1002 |
List<Person> list = team.getTeamMembers();
|
|
1003 |
for(int i = 0; i < list.size(); i++){
|
|
1004 |
Person person = list.get(i);
|
|
1005 |
Person tmpMember = normalizePerson(person);
|
|
1006 |
list.set(i, tmpMember);
|
|
1007 |
}
|
|
1008 |
return team;
|
|
1009 |
}
|
|
1010 |
return result;
|
|
1011 |
}
|
|
1012 |
|
|
1013 |
|
|
1014 |
/**
|
|
1015 |
* @param deproxy
|
|
1016 |
* @return
|
|
1017 |
*/
|
|
1018 |
private Person normalizePerson(Person person) {
|
|
1019 |
String title = person.getNomenclaturalTitle();
|
|
1020 |
title = title.replaceAll("(?<=[a-zA-Z])\\.(?=[a-zA-Z])", ". ");
|
|
1021 |
person.setNomenclaturalTitle(title);
|
|
1022 |
boolean isFilius = title.endsWith(" f.");
|
|
1023 |
if (isFilius){
|
|
1024 |
title.replace(" f.", "");
|
|
1025 |
}
|
|
1026 |
|
|
1027 |
String[] splits = title.split("\\s+");
|
|
1028 |
int nNotFirstName = isFilius ? 2 : 1;
|
|
1029 |
person.setLastname(splits[splits.length - nNotFirstName] + (isFilius? " f." : ""));
|
|
1030 |
person.setFirstname(CdmUtils.concat(" ", Arrays.copyOfRange(splits, 0, splits.length-nNotFirstName)));
|
|
1031 |
return person;
|
|
1032 |
}
|
|
1033 |
|
|
1034 |
|
692 |
1035 |
/**
|
693 |
1036 |
* @param state
|
694 |
1037 |
* @return
|
... | ... | |
739 |
1082 |
if (familyStr == null){
|
740 |
1083 |
return null;
|
741 |
1084 |
}
|
|
1085 |
familyStr = familyStr.trim();
|
|
1086 |
String alternativeFamilyStr = null;
|
|
1087 |
if (familyStr.contains("/")){
|
|
1088 |
String[] splits = familyStr.split("/");
|
|
1089 |
if (splits.length > 2){
|
|
1090 |
logger.warn(state.getCurrentLine() +": " + "More than 1 alternative name:" + familyStr);
|
|
1091 |
}
|
|
1092 |
familyStr = splits[0].trim();
|
|
1093 |
alternativeFamilyStr = splits[1].trim();
|
|
1094 |
}
|
|
1095 |
|
742 |
1096 |
Taxon family = state.getHigherTaxon(familyStr);
|
743 |
1097 |
TaxonNode familyNode;
|
744 |
1098 |
if (family != null){
|
745 |
1099 |
familyNode = family.getTaxonNodes().iterator().next();
|
746 |
1100 |
}else{
|
747 |
|
BotanicalName name = state.getFamilyName(familyStr);
|
748 |
|
if (name == null){
|
749 |
|
name = BotanicalName.NewInstance(Rank.FAMILY());
|
750 |
|
name.setGenusOrUninomial(familyStr);
|
751 |
|
state.putFamilyName(familyStr, name);
|
752 |
|
}
|
|
1101 |
BotanicalName name = makeFamilyName(state, familyStr);
|
753 |
1102 |
Reference<?> sec = getSecReference(state);
|
754 |
|
Taxon taxon = Taxon.NewInstance(name, sec);
|
|
1103 |
family = Taxon.NewInstance(name, sec);
|
755 |
1104 |
ITaxonTreeNode rootNode = getClassification(state);
|
756 |
|
familyNode = rootNode.addChildTaxon(taxon, sec, null);
|
757 |
|
state.putHigherTaxon(familyStr, taxon);
|
|
1105 |
familyNode = rootNode.addChildTaxon(family, sec, null);
|
|
1106 |
state.putHigherTaxon(familyStr, family);
|
|
1107 |
|
|
1108 |
}
|
|
1109 |
|
|
1110 |
if (isNotBlank(alternativeFamilyStr)){
|
|
1111 |
NameRelationshipType type = NameRelationshipType.ALTERNATIVE_NAME();
|
|
1112 |
BotanicalName alternativeName = makeFamilyName(state, alternativeFamilyStr);
|
|
1113 |
BotanicalName familyName = (BotanicalName)family.getName();
|
|
1114 |
boolean hasRelation = false;
|
|
1115 |
for (NameRelationship nameRel : familyName.getRelationsToThisName()){
|
|
1116 |
if (nameRel.getType().equals(type)){
|
|
1117 |
if (nameRel.getFromName().equals(alternativeName)){
|
|
1118 |
hasRelation = true;
|
|
1119 |
}
|
|
1120 |
}
|
|
1121 |
}
|
|
1122 |
if (!hasRelation){
|
|
1123 |
familyName.addRelationshipFromName(alternativeName, type, null);
|
|
1124 |
}
|
|
1125 |
|
758 |
1126 |
}
|
759 |
1127 |
|
760 |
1128 |
return familyNode;
|
761 |
1129 |
}
|
762 |
1130 |
|
|
1131 |
|
|
1132 |
/**
|
|
1133 |
* @param state
|
|
1134 |
* @param taxon
|
|
1135 |
*/
|
|
1136 |
private void validateTaxonIsAbsent(CubaImportState state, Taxon taxon) {
|
|
1137 |
if (!state.isTaxonIsAbsent()){
|
|
1138 |
return;
|
|
1139 |
}
|
|
1140 |
|
|
1141 |
for (DescriptionElementBase el : taxon.getDescriptions().iterator().next().getElements()){
|
|
1142 |
if (el instanceof Distribution){
|
|
1143 |
Distribution dist = (Distribution)el;
|
|
1144 |
NamedArea area = dist.getArea();
|
|
1145 |
if (isCubanArea(area)){
|
|
1146 |
PresenceAbsenceTerm status = dist.getStatus();
|
|
1147 |
if (status != null && !status.isAbsenceTerm()){
|
|
1148 |
if (!isDoubtfulTerm(status)){
|
|
1149 |
String name = taxon.getName().getTitleCache();
|
|
1150 |
logger.error(state.getCurrentLine() +": Taxon ("+name+")is absent'[]' but has presence distribution: " + status.getTitleCache());
|
|
1151 |
return;
|
|
1152 |
}
|
|
1153 |
}
|
|
1154 |
}
|
|
1155 |
}
|
|
1156 |
}
|
|
1157 |
}
|
|
1158 |
|
|
1159 |
/**
|
|
1160 |
* @param state
|
|
1161 |
* @param taxon
|
|
1162 |
*/
|
|
1163 |
private void validateEndemic(CubaImportState state, Taxon taxon) {
|
|
1164 |
|
|
1165 |
boolean hasExternalPresence = false;
|
|
1166 |
for (DescriptionElementBase el : taxon.getDescriptions().iterator().next().getElements()){
|
|
1167 |
if (el instanceof Distribution){
|
|
1168 |
Distribution dist = (Distribution)el;
|
|
1169 |
NamedArea area = dist.getArea();
|
|
1170 |
if (!isCubanArea(area)){
|
|
1171 |
PresenceAbsenceTerm status = dist.getStatus();
|
|
1172 |
if (status != null && !status.isAbsenceTerm()){
|
|
1173 |
if (!isDoubtfulTerm(status)){
|
|
1174 |
hasExternalPresence = true;
|
|
1175 |
if (state.isEndemic()){
|
|
1176 |
String name = taxon.getName().getTitleCache();
|
|
1177 |
logger.error(state.getCurrentLine() +": Taxon ("+name+")is endemic but has non-cuban distribution: " + area.getIdInVocabulary() + "-" + status.getIdInVocabulary());
|
|
1178 |
return;
|
|
1179 |
}
|
|
1180 |
}
|
|
1181 |
}
|
|
1182 |
}
|
|
1183 |
}
|
|
1184 |
}
|
|
1185 |
if (!state.isEndemic() && ! hasExternalPresence){
|
|
1186 |
String name = taxon.getName().getTitleCache();
|
|
1187 |
logger.error(state.getCurrentLine() +": Taxon ("+name+")is not endemic but has no non-cuban distribution" );
|
|
1188 |
}
|
|
1189 |
}
|
|
1190 |
|
|
1191 |
|
763 |
1192 |
/**
|
764 |
1193 |
* @param state
|
765 |
1194 |
* @param taxon
|
... | ... | |
771 |
1200 |
String key = famRef.getTitle() + ":"+ famStr;
|
772 |
1201 |
Taxon family = state.getHigherTaxon(key);
|
773 |
1202 |
if (family == null){
|
774 |
|
BotanicalName name = state.getFamilyName(famStr);
|
775 |
|
if (name == null){
|
776 |
|
name = BotanicalName.NewInstance(Rank.FAMILY());
|
777 |
|
name.setGenusOrUninomial(famStr);
|
778 |
|
state.putFamilyName(famStr, name);
|
779 |
|
}
|
|
1203 |
BotanicalName name = makeFamilyName(state, famStr);
|
780 |
1204 |
family = Taxon.NewInstance(name, famRef);
|
781 |
1205 |
state.putHigherTaxon(key, family);
|
782 |
1206 |
}
|
... | ... | |
785 |
1209 |
}
|
786 |
1210 |
|
787 |
1211 |
|
|
1212 |
/**
|
|
1213 |
* @param state
|
|
1214 |
* @param famStr
|
|
1215 |
* @return
|
|
1216 |
*/
|
|
1217 |
private BotanicalName makeFamilyName(CubaImportState state, String famStr) {
|
|
1218 |
BotanicalName name = state.getFamilyName(famStr);
|
|
1219 |
if (name == null){
|
|
1220 |
name = BotanicalName.NewInstance(Rank.FAMILY());
|
|
1221 |
name.setGenusOrUninomial(famStr);
|
|
1222 |
state.putFamilyName(famStr, name);
|
|
1223 |
name.addSource(makeOriginalSource(state));
|
|
1224 |
}
|
|
1225 |
return name;
|
|
1226 |
}
|
|
1227 |
|
|
1228 |
|
788 |
1229 |
/**
|
789 |
1230 |
* @param state
|
790 |
1231 |
* @return
|
... | ... | |
847 |
1288 |
*/
|
848 |
1289 |
@Override
|
849 |
1290 |
protected void firstPass(CubaImportState state) {
|
850 |
|
boolean isSynonym = false;
|
|
1291 |
boolean isSynonymOnly = false;
|
851 |
1292 |
|
852 |
1293 |
String line = state.getCurrentLine() + ": ";
|
853 |
1294 |
HashMap<String, String> record = state.getOriginalRecord();
|
... | ... | |
874 |
1315 |
logger.warn(line + "Family not recognized but also no synonym exists");
|
875 |
1316 |
return;
|
876 |
1317 |
}else{
|
877 |
|
isSynonym = true;
|
|
1318 |
isSynonymOnly = true;
|
878 |
1319 |
}
|
879 |
1320 |
}
|
880 |
1321 |
|
881 |
|
|
882 |
|
|
883 |
|
//Taxón
|
884 |
|
Taxon taxon = makeTaxon(record, state, familyTaxon, isSynonym);
|
885 |
|
if (taxon == null && ! isSynonym){
|
|
1322 |
//Taxón
|
|
1323 |
Taxon taxon = makeTaxon(record, state, familyTaxon, isSynonymOnly);
|
|
1324 |
if (taxon == null && ! isSynonymOnly){
|
886 |
1325 |
logger.warn(line + "taxon could not be created and is null");
|
887 |
1326 |
return;
|
888 |
1327 |
}
|
... | ... | |
895 |
1334 |
makeNotes(record, state);
|
896 |
1335 |
|
897 |
1336 |
//Syn.
|
898 |
|
makeSynonyms(record, state);
|
|
1337 |
makeSynonyms(record, state, !isSynonymOnly);
|
899 |
1338 |
|
900 |
1339 |
//End, Ind, Ind? D, Nat N, Dud P, Adv A, Cult C
|
901 |
1340 |
makeCubanDistribution(record, state);
|
... | ... | |
910 |
1349 |
// "AmN","AmC","AmS","VM"});
|
911 |
1350 |
makeOtherAreasDistribution(record, state);
|
912 |
1351 |
|
|
1352 |
validateTaxonIsAbsent(state, taxon);
|
|
1353 |
if (!isSynonymOnly){
|
|
1354 |
validateEndemic(state, taxon);
|
|
1355 |
}
|
913 |
1356 |
|
914 |
1357 |
state.setHighestStatusForTaxon(null);
|
915 |
1358 |
|
... | ... | |
917 |
1360 |
}
|
918 |
1361 |
|
919 |
1362 |
|
|
1363 |
/**
|
|
1364 |
* @param state
|
|
1365 |
* @return
|
|
1366 |
*/
|
|
1367 |
private IdentifiableSource makeOriginalSource(CubaImportState state) {
|
|
1368 |
return IdentifiableSource.NewDataImportInstance("line: " + state.getCurrentLine(), null, state.getConfig().getSourceReference());
|
|
1369 |
}
|
|
1370 |
/**
|
|
1371 |
* @param state
|
|
1372 |
* @return
|
|
1373 |
*/
|
|
1374 |
private DescriptionElementSource makeDescriptionSource(CubaImportState state) {
|
|
1375 |
return DescriptionElementSource.NewDataImportInstance("line: " + state.getCurrentLine(), null, state.getConfig().getSourceReference());
|
|
1376 |
}
|
|
1377 |
|
|
1378 |
private static Set<UUID> doubtfulStatus = new HashSet<>();
|
920 |
1379 |
|
921 |
|
/**
|
|
1380 |
/**
|
|
1381 |
* @param status
|
|
1382 |
* @return
|
|
1383 |
*/
|
|
1384 |
private boolean isDoubtfulTerm(PresenceAbsenceTerm status) {
|
|
1385 |
if (doubtfulStatus.isEmpty()){
|
|
1386 |
doubtfulStatus.add(CubaTransformer.nonNativeDoubtfullyNaturalisedUuid);
|
|
1387 |
doubtfulStatus.add(CubaTransformer.doubtfulIndigenousDoubtfulUuid);
|
|
1388 |
doubtfulStatus.add(CubaTransformer.endemicDoubtfullyPresentUuid);
|
|
1389 |
doubtfulStatus.add(CubaTransformer.naturalisedDoubtfullyPresentUuid);
|
|
1390 |
doubtfulStatus.add(CubaTransformer.nonNativeDoubtfullyPresentUuid);
|
|
1391 |
doubtfulStatus.add(CubaTransformer.occasionallyCultivatedUuid);
|
|
1392 |
doubtfulStatus.add(CubaTransformer.rareCasualUuid);
|
|
1393 |
doubtfulStatus.add(PresenceAbsenceTerm.NATIVE_PRESENCE_QUESTIONABLE().getUuid());
|
|
1394 |
doubtfulStatus.add(PresenceAbsenceTerm.CULTIVATED_PRESENCE_QUESTIONABLE().getUuid());
|
|
1395 |
}
|
|
1396 |
boolean isDoubtful = doubtfulStatus.contains(status.getUuid());
|
|
1397 |
return isDoubtful;
|
|
1398 |
}
|
|
1399 |
|
|
1400 |
|
|
1401 |
/**
|
|
1402 |
* @param area
|
|
1403 |
* @return
|
|
1404 |
*/
|
|
1405 |
private boolean isCubanArea(NamedArea area) {
|
|
1406 |
if (area.getUuid().equals(CubaTransformer.uuidCuba)){
|
|
1407 |
return true;
|
|
1408 |
}else if (area.getPartOf()!= null){
|
|
1409 |
return isCubanArea(area.getPartOf());
|
|
1410 |
}else{
|
|
1411 |
return false;
|
|
1412 |
}
|
|
1413 |
}
|
|
1414 |
|
|
1415 |
|
|
1416 |
/**
|
922 |
1417 |
* @param record
|
923 |
1418 |
* @param state
|
924 |
1419 |
* @param familyTaxon
|
... | ... | |
1041 |
1536 |
}
|
1042 |
1537 |
|
1043 |
1538 |
|
1044 |
|
/**
|
1045 |
|
* @param areaKey
|
1046 |
|
* @param record
|
1047 |
|
* @param state
|
1048 |
|
* @param taxon
|
1049 |
|
*/
|
1050 |
|
private void makeSingleProvinceDistribution(String areaKey,
|
1051 |
|
HashMap<String, String> record,
|
1052 |
|
CubaImportState state) {
|
1053 |
|
try {
|
1054 |
|
UUID areaUuid = state.getTransformer().getNamedAreaUuid(areaKey);
|
1055 |
|
if (areaUuid == null){
|
1056 |
|
logger.warn("Area not recognized: " + areaKey);
|
1057 |
|
return;
|
1058 |
|
}
|
1059 |
|
if (record.get(areaKey)==null){
|
1060 |
|
return; //no status defined
|
1061 |
|
}
|
1062 |
|
|
1063 |
|
NamedArea area = getNamedArea(state, areaUuid, null, null, null, null, null);
|
1064 |
|
if (area == null){
|
1065 |
|
logger.warn(state.getCurrentLine() + ": Area not recognized: " + area);
|
1066 |
|
}
|
1067 |
|
TaxonDescription desc = getTaxonDescription(state.getCurrentTaxon(), false, true);
|
1068 |
|
PresenceAbsenceTerm status = makeProvinceStatus(areaKey, record, state);
|
1069 |
|
if (status == null){
|
1070 |
|
logger.warn(state.getCurrentLine() + ": Province distribution status could not be defined: " + record.get(areaKey));
|
1071 |
|
}
|
1072 |
|
Distribution distribution = Distribution.NewInstance(area, status);
|
1073 |
|
desc.addElement(distribution);
|
1074 |
|
} catch (UndefinedTransformerMethodException e) {
|
1075 |
|
e.printStackTrace();
|
1076 |
|
}
|
1077 |
|
|
1078 |
|
}
|
1079 |
1539 |
|
1080 |
1540 |
|
1081 |
1541 |
/**
|
... | ... | |
1093 |
1553 |
String statusStr = record.get(areaKey);
|
1094 |
1554 |
if (statusStr == null){
|
1095 |
1555 |
return null;
|
|
1556 |
}else{
|
|
1557 |
statusStr = statusStr.trim();
|
1096 |
1558 |
}
|
1097 |
1559 |
PresenceAbsenceTerm status = state.getTransformer().getPresenceTermByKey(statusStr);
|
1098 |
1560 |
if (status == null){
|
1099 |
|
PresenceAbsenceTerm highestStatus = state.getHighestStatusForTaxon();
|
|
1561 |
// PresenceAbsenceTerm highestStatus = state.getHighestStatusForTaxon();
|
1100 |
1562 |
if (state.isCubanProvince() && isMinus(statusStr)){
|
1101 |
|
getAbsenceTermForStatus(state, highestStatus);
|
|
1563 |
// getAbsenceTermForStatus(state, highestStatus);
|
|
1564 |
//we now handle cuban provinces same as external regions
|
|
1565 |
status = state.getTransformer().getPresenceTermByKey("--");
|
1102 |
1566 |
}else if (! state.isCubanProvince() && isMinus(statusStr)){
|
1103 |
1567 |
status = state.getTransformer().getPresenceTermByKey("--");
|
1104 |
1568 |
}else{
|
|
1569 |
// logger.warn("Unhandled status str for provinces / external regions: " + statusStr);
|
1105 |
1570 |
UUID statusUuid = state.getTransformer().getPresenceTermUuid(statusStr);
|
1106 |
|
status = getPresenceTerm(state, statusUuid, null, null, null, false);
|
|
1571 |
if (statusUuid == null){
|
|
1572 |
logger.error(state.getCurrentLine() + ": Undefined status str for provinces / external regions. No UUID given: '" + statusStr + "'");
|
|
1573 |
}else{
|
|
1574 |
status = getPresenceTerm(state, statusUuid, statusStr, statusStr, statusStr, false);
|
|
1575 |
}
|
1107 |
1576 |
}
|
1108 |
1577 |
}
|
1109 |
1578 |
|
Latest changes to Cuba import