rename cdmlib-eflora -> cdm-eflora
[cdmlib-apps.git] / cdm-eflora / src / main / java / eu / etaxonomy / cdm / io / eflora / centralAfrica / ferns / CentralAfricaFernsTaxonRelationImport.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.cdm.io.eflora.centralAfrica.ferns;
11
12 import java.sql.ResultSet;
13 import java.sql.SQLException;
14 import java.util.Arrays;
15 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Set;
20 import java.util.UUID;
21
22 import org.apache.commons.lang.StringUtils;
23 import org.apache.log4j.Logger;
24 import org.springframework.stereotype.Component;
25
26 import eu.etaxonomy.cdm.api.service.IClassificationService;
27 import eu.etaxonomy.cdm.common.CdmUtils;
28 import eu.etaxonomy.cdm.io.common.IOValidator;
29 import eu.etaxonomy.cdm.io.common.mapping.DbImportMapping;
30 import eu.etaxonomy.cdm.io.common.mapping.DbImportMethodMapper;
31 import eu.etaxonomy.cdm.io.common.mapping.DbImportTaxIncludedInMapper;
32 import eu.etaxonomy.cdm.io.common.mapping.IMappingImport;
33 import eu.etaxonomy.cdm.io.common.mapping.UndefinedTransformerMethodException;
34 import eu.etaxonomy.cdm.io.eflora.centralAfrica.ferns.validation.CentralAfricaFernsTaxonImportValidator;
35 import eu.etaxonomy.cdm.model.agent.INomenclaturalAuthor;
36 import eu.etaxonomy.cdm.model.common.CdmBase;
37 import eu.etaxonomy.cdm.model.common.Language;
38 import eu.etaxonomy.cdm.model.description.CommonTaxonName;
39 import eu.etaxonomy.cdm.model.description.Distribution;
40 import eu.etaxonomy.cdm.model.description.Feature;
41 import eu.etaxonomy.cdm.model.description.PresenceTerm;
42 import eu.etaxonomy.cdm.model.description.TaxonDescription;
43 import eu.etaxonomy.cdm.model.description.TextData;
44 import eu.etaxonomy.cdm.model.location.NamedArea;
45 import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
46 import eu.etaxonomy.cdm.model.location.NamedAreaType;
47 import eu.etaxonomy.cdm.model.location.TdwgArea;
48 import eu.etaxonomy.cdm.model.location.WaterbodyOrCountry;
49 import eu.etaxonomy.cdm.model.name.BotanicalName;
50 import eu.etaxonomy.cdm.model.name.NonViralName;
51 import eu.etaxonomy.cdm.model.name.Rank;
52 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
53 import eu.etaxonomy.cdm.model.reference.Reference;
54 import eu.etaxonomy.cdm.model.taxon.Classification;
55 import eu.etaxonomy.cdm.model.taxon.Synonym;
56 import eu.etaxonomy.cdm.model.taxon.SynonymRelationship;
57 import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
58 import eu.etaxonomy.cdm.model.taxon.Taxon;
59 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
60 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
61
62
63 /**
64 * @author a.mueller
65 */
66
67 @Component
68 public class CentralAfricaFernsTaxonRelationImport extends CentralAfricaFernsImportBase<TaxonBase> implements IMappingImport<TaxonBase, CentralAfricaFernsImportState>{
69 private static final Logger logger = Logger.getLogger(CentralAfricaFernsTaxonRelationImport.class);
70
71 private DbImportMapping mapping;
72
73
74 private static final String pluralString = "taxon relations";
75 private static final String dbTableName = "[African pteridophytes]";
76 private static final Class cdmTargetClass = TaxonBase.class;
77
78 private Map<String, UUID> nameCacheTaxonMap = new HashMap<String, UUID>();
79 private Map<String, UUID> titleCacheTaxonMap = new HashMap<String, UUID>();
80
81 private CentralAfricaFernsImportState state;
82
83
84 public CentralAfricaFernsTaxonRelationImport(){
85 super(pluralString, dbTableName, cdmTargetClass);
86 }
87
88
89
90 /* (non-Javadoc)
91 * @see eu.etaxonomy.cdm.io.erms.ErmsImportBase#getIdQuery()
92 */
93 @Override
94 protected String getIdQuery() {
95 String strQuery = " SELECT [Taxon number] FROM " + dbTableName;;
96 return strQuery;
97 }
98
99
100 /* (non-Javadoc)
101 * @see eu.etaxonomy.cdm.io.eflora.centralAfrica.ferns.CentralAfricaFernsImportBase#getMapping()
102 */
103 @Override
104 protected DbImportMapping getMapping() {
105 if (mapping == null){
106 mapping = new DbImportMapping();
107
108 mapping.addMapper(DbImportMethodMapper.NewInstance(this, "createObject", ResultSet.class, CentralAfricaFernsImportState.class));
109 mapping.addMapper(DbImportMethodMapper.NewInstance(this, "mapCommonName", ResultSet.class, CentralAfricaFernsImportState.class));
110 mapping.addMapper(DbImportMethodMapper.NewInstance(this, "mapDistribution", ResultSet.class, CentralAfricaFernsImportState.class ));
111 mapping.addMapper(DbImportMethodMapper.NewInstance(this, "mapEcology", ResultSet.class, CentralAfricaFernsImportState.class));
112
113 }
114 return mapping;
115 }
116
117 /* (non-Javadoc)
118 * @see eu.etaxonomy.cdm.io.eflora.centralAfrica.ferns.CentralAfricaFernsImportBase#getRecordQuery(eu.etaxonomy.cdm.io.eflora.centralAfrica.ferns.CentralAfricaFernsImportConfigurator)
119 */
120 @Override
121 protected String getRecordQuery(CentralAfricaFernsImportConfigurator config) {
122 String strSelect = " SELECT * ";
123 String strFrom = " FROM [African pteridophytes] as ap";
124 String strWhere = " WHERE ( ap.[taxon number] IN (" + ID_LIST_TOKEN + ") )";
125 String strOrderBy = " ORDER BY [Taxon number]";
126 String strRecordQuery = strSelect + strFrom + strWhere + strOrderBy ;
127 return strRecordQuery;
128 }
129
130
131 /* (non-Javadoc)
132 * @see eu.etaxonomy.cdm.io.eflora.centralAfrica.ferns.CentralAfricaFernsImportBase#doInvoke(eu.etaxonomy.cdm.io.eflora.centralAfrica.ferns.CentralAfricaFernsImportState)
133 */
134 @Override
135 protected void doInvoke(CentralAfricaFernsImportState state) {
136 this.state = state;
137 fillTaxonMap();
138 super.doInvoke(state);
139 return;
140 }
141
142
143 /**
144 * Fills the nameCache and the titleCache maps. The maps are used to find existing taxa
145 * by titleCache or nameCache matching.
146 * Matching may be implemented more sophisticated in future versions.
147 */
148 private void fillTaxonMap() {
149 List<String> propPath = Arrays.asList(new String []{"name"});
150
151 List<Taxon> taxonList = (List)getTaxonService().list(Taxon.class, null, null, null, propPath );
152 for (Taxon taxon : taxonList){
153 NonViralName nvn = CdmBase.deproxy(taxon.getName(), NonViralName.class);
154 UUID uuid = taxon.getUuid();
155 String nameCache = nvn.getNameCache();
156 String titleCache = nvn.getTitleCache();
157 nameCacheTaxonMap.put(nameCache, uuid);
158 titleCacheTaxonMap.put(titleCache, uuid);
159 }
160 }
161
162 /* (non-Javadoc)
163 * @see eu.etaxonomy.cdm.io.common.IPartitionedIO#getRelatedObjectsForPartition(java.sql.ResultSet)
164 */
165 public Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForPartition(ResultSet rs) {
166 String nameSpace;
167 Class cdmClass;
168 Set<String> idSet;
169 Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<Object, Map<String, ? extends CdmBase>>();
170
171 try{
172 Set<String> taxonIdSet = new HashSet<String>();
173 // Set<String> referenceIdSet = new HashSet<String>();
174 while (rs.next()){
175 handleForeignKey(rs, taxonIdSet, "Current");
176 handleForeignKey(rs, taxonIdSet, "Taxon number");
177 // handleForeignKey(rs, referenceIdSet, "PTRefFk");
178 }
179
180 //taxon map
181 nameSpace = TAXON_NAMESPACE;
182 cdmClass = TaxonBase.class;
183 Map<String, TaxonBase> taxonMap = (Map<String, TaxonBase>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, taxonIdSet, nameSpace);
184 result.put(nameSpace, taxonMap);
185
186
187 //reference map
188 this.sourceReference = getFernsSourceReference(state);
189 // nameSpace = "Reference";
190 // cdmClass = Reference.class;
191 // Map<String, Person> referenceMap = (Map<String, Person>)getCommonService().getSourcedObjectsByIdInSource(Person.class, teamIdSet, nameSpace);
192 // result.put(Reference.class, referenceMap);
193
194 } catch (SQLException e) {
195 throw new RuntimeException(e);
196 }
197 return result;
198 }
199
200
201 /* (non-Javadoc)
202 * @see eu.etaxonomy.cdm.io.common.mapping.IMappingImport#createObject(java.sql.ResultSet, eu.etaxonomy.cdm.io.common.ImportStateBase)
203 */
204 @Override
205 public TaxonBase createObject(ResultSet rs, CentralAfricaFernsImportState state) throws SQLException {
206 TaxonBase result = null;
207 try {
208 String status = rs.getString("Current/Synonym");
209 String taxonNumber = rs.getString("Taxon number");
210 state.setTaxonNumber(taxonNumber);
211 if ("s".equalsIgnoreCase(status)){
212 //synonym
213 result = handleSynonym(rs, state);
214 }else{
215 //accepted Taxon
216 result = handleTaxon(rs, state);
217 }
218
219 return result;
220 } catch (Exception e) {
221 e.printStackTrace();
222 return result;
223 }
224
225 }
226
227
228 /**
229 * Class to store all epithets of the database record. Maybe extended with business logic.
230 */
231 private class Epithets{
232 private String orderName;
233 private String subOrderName;
234 private String familyName;
235 private String subFamilyName;
236 private String tribusName;
237 private String subTribusName;
238 private String sectionName;
239 private String subsectionName;
240 private String genusName;
241 private String subGenusName;
242 private String seriesName;
243 private String specificEpithet;
244 private String subspeciesName;
245 private String varietyName;
246 private String subVariety;
247 private String formaName;
248 private String subFormaName;
249 }
250
251
252 /**
253 * Handles records with status synonym. A synonym relationship to the accepted taxon
254 * is created.
255 * @param rs
256 * @param state
257 * @return
258 * @throws SQLException
259 */
260 private Synonym handleSynonym(ResultSet rs, CentralAfricaFernsImportState state) throws SQLException {
261 String accTaxonId = rs.getString("Current");
262 String nomRemarksString = rs.getString("Current/Synonym");
263
264 String synonymId = state.getTaxonNumber();
265 Synonym synonym = (Synonym)state.getRelatedObject(TAXON_NAMESPACE, synonymId);
266 if (synonym == null){
267 logger.warn ("Synonym ("+synonymId+")not found.");
268 return null;
269 }
270 TaxonBase taxonBase = CdmBase.deproxy(state.getRelatedObject(TAXON_NAMESPACE, accTaxonId), TaxonBase.class);
271
272 if (taxonBase != null){
273 if (taxonBase.isInstanceOf(Taxon.class)){
274 Taxon taxon = CdmBase.deproxy(taxonBase, Taxon.class);
275 SynonymRelationship rel = taxon.addSynonym(synonym, SynonymRelationshipType.SYNONYM_OF());
276 if ("p.p.".equalsIgnoreCase(nomRemarksString)){
277 rel.setProParte(true);
278 }
279 }else{
280 logger.warn("Accepted taxon (" + accTaxonId + ") for synonym (" + synonymId +") is not of type 'Current'");
281 }
282 }else{
283 logger.warn("Taxon (" + accTaxonId + ") not found for synonym (" + synonymId +")");
284 }
285
286 return synonym;
287 }
288
289
290 /**
291 * Handles all records with status 'current'. Creates parent-child relationships to the
292 * higher taxa. Uses a complex algorithm to reuse existing higher taxa.
293 * @param rs
294 * @param state
295 * @return
296 * @throws SQLException
297 */
298 private Taxon handleTaxon(ResultSet rs, CentralAfricaFernsImportState state) throws SQLException {
299 String taxonNumber = rs.getString("Taxon number");
300 Taxon child = (Taxon)state.getRelatedObject(TAXON_NAMESPACE, taxonNumber);
301 if (child == null){
302 logger.warn("Taxon does not exist: " + taxonNumber);
303 return null;
304 }
305 Epithets epithets = new Epithets();
306 epithets.orderName = rs.getString("Order name");
307 epithets.subOrderName = rs.getString("Suborder name");
308 epithets.familyName = rs.getString("Family name");
309 epithets.subFamilyName = rs.getString("Subfamily name");
310 epithets.tribusName = rs.getString("Tribus name");
311 epithets.subTribusName = rs.getString("Subtribus name");
312 epithets.sectionName = rs.getString("Section name");
313 epithets.subsectionName = rs.getString("Subsection name");
314 epithets.genusName = rs.getString("Genus name");
315 epithets.subGenusName = rs.getString("Subgenus name");
316 epithets.seriesName = rs.getString("Series name");
317 epithets.specificEpithet = rs.getString("Specific epihet");
318 epithets.subspeciesName = rs.getString("Subspecies name");
319 epithets.varietyName = rs.getString("Variety name");
320 epithets.subVariety = rs.getString("Subvariery");
321 epithets.formaName = rs.getString("Forma name");
322 epithets.subFormaName = rs.getString("Subforma");
323
324 makeNextHigherTaxon(state, rs, child, epithets);
325 return child;
326 }
327
328
329 /**
330 * Adds recursively this taxon to the next higher taxon. If the taxon exists already
331 * the relationship is not added again.<BR>
332 * If the author is missing in the old taxon but not in the new taxon the
333 * old taxon will get the new taxons author.(NOT VALID ANY MORE)<BR>
334 * If authors differ a new taxon is created.<BR>
335 * If a higher taxon exists the method is called recursively on this taxon.
336 * @throws SQLException
337 */
338 private void makeNextHigherTaxon(CentralAfricaFernsImportState state, ResultSet rs, Taxon child, Epithets epithets) throws SQLException {
339
340 Taxon constructedHigherTaxon = constructNextHigherTaxon(state, rs, child, epithets);
341 Reference<?> citation = null;
342 String microcitation = null;
343
344 if (constructedHigherTaxon != null){
345 handleHigherTaxonMustExist(state, rs, child, epithets, constructedHigherTaxon, citation, microcitation);
346 }else{
347 //add taxon to tree if not yet added
348 if (child.getTaxonNodes().size() == 0){
349 makeTaxonomicallyIncluded(state, null, child, null, citation, microcitation);
350 }
351 }
352 }
353
354
355
356 /**
357 * Handles the case when the database record has data for a taxon of a higher rank
358 * than the <code>child</code> taxon's rank.
359 * @param state
360 * @param rs
361 * @param child
362 * @param epithets
363 * @param higherTaxon
364 * @param citation
365 * @param microcitation
366 * @throws SQLException
367 */
368 private void handleHigherTaxonMustExist(CentralAfricaFernsImportState state, ResultSet rs, Taxon child, Epithets epithets, Taxon constructedHigherTaxon, Reference<?> citation, String microCitation) throws SQLException {
369 Taxon parentTaxon = getParent(child);
370 if (parentTaxon == null){
371 //if no parent taxon exists
372 Taxon existingTaxon = findExistingNonParentTaxon(state, constructedHigherTaxon);
373 if (existingTaxon != null){
374 //a taxon with same title cache or same name cache exists
375 parentTaxon = mergeExistingAndConstructedTaxon(state, existingTaxon, constructedHigherTaxon);
376 }else{
377 parentTaxon = constructedHigherTaxon;
378 }
379 makeTaxonomicallyIncluded(state, null, child, parentTaxon, citation, microCitation);
380 }else{
381 //parent taxon exists
382 if (namesMatch(parentTaxon, constructedHigherTaxon)){
383 //parents match
384 //TODO what if the higher taxonomy does not match
385 parentTaxon = mergeExistingAndConstructedTaxon(state, parentTaxon, constructedHigherTaxon);
386 }else if (compareRanks(parentTaxon, constructedHigherTaxon) != 0){
387 //ranks unequal
388 parentTaxon = handleUnequalRanks(parentTaxon, constructedHigherTaxon);
389 }else if (! nameCachesMatch(parentTaxon, constructedHigherTaxon)){
390 //nameCache not equal
391 parentTaxon = handleUnequalNameCaches(parentTaxon, constructedHigherTaxon);
392 }else if (! authorsMatch(parentTaxon, constructedHigherTaxon)){
393 //nameCache not equal
394 parentTaxon = handleUnequalAuthors(parentTaxon, constructedHigherTaxon);
395 }
396 }
397 //save the parent taxon, if it is new
398 if (parentTaxon == constructedHigherTaxon){
399 saveConstructedTaxon(state, constructedHigherTaxon);
400 }
401 makeNextHigherTaxon(state, rs, parentTaxon, epithets);
402 }
403
404
405 /**
406 * Merges author information of the constructed taxon into the existing taxon.
407 * Returns the existing taxon.
408 * @param state
409 * @param parentTaxon
410 * @param constructedHigherTaxon
411 */
412 private Taxon mergeExistingAndConstructedTaxon(CentralAfricaFernsImportState state, Taxon existingTaxon, Taxon constructedTaxon) {
413 NonViralName constructedName = CdmBase.deproxy(constructedTaxon.getName(), NonViralName.class);
414 NonViralName existingName = CdmBase.deproxy(existingTaxon.getName(), NonViralName.class);
415 if (constructedName.hasAuthors()){
416 if (! existingName.hasAuthors()){
417 logger.warn(state.getTaxonNumber() + " - Constrcucted name ("+constructedName.getTitleCache()+") has authors but existing name ("+existingName.getTitleCache()+") has no authors");
418 }else if (! authorsMatch(constructedName, existingName)){
419 logger.warn(state.getTaxonNumber() + " - Constrcucted name ("+constructedName.getTitleCache()+") and existing name ("+existingName.getTitleCache()+") have different authors");
420 }else {
421 //authors match and are not null
422 }
423 }
424 // more?
425 return existingTaxon;
426 }
427
428
429 /**
430 * Strategy for the decision if an existing parent or a constructed higher taxon should
431 * be taken as parent in case that the authors of the name differ somehow.
432 * Current strategy: use existing parent if constructed higher taxon has no authors
433 * at all. Use constructed taxon otherwise.
434 * @param existingParentTaxon
435 * @param constructedHigherTaxon
436 * @return
437 */
438 private Taxon handleUnequalAuthors(Taxon existingParentTaxon, Taxon constructedHigherTaxon) {
439 Taxon result;
440 BotanicalName existingName = CdmBase.deproxy(existingParentTaxon.getName(), BotanicalName.class);
441 BotanicalName constructedName = (BotanicalName)constructedHigherTaxon.getName();
442 //current strategy: if constructedName has no authors (and parentName has
443 if (! constructedName.hasAuthors()){
444 result = existingParentTaxon;
445 }else if (! existingName.hasAuthors()){
446 result = constructedHigherTaxon;
447 }else{
448 result = constructedHigherTaxon;
449 }
450 return result;
451 }
452
453 /**
454 * Strategy for the decision if an existing parent or a constructed higher taxon
455 * should be taken as parent in case that the name caches differ somehow.
456 * Current strategy: Not implemented. Always use constructed higher taxon.
457 * @param existingParentTaxon
458 * @param constructedHigherTaxon
459 * @return
460 */
461 private Taxon handleUnequalNameCaches(Taxon parentTaxon, Taxon constructedHigherTaxon) {
462 BotanicalName parentName = CdmBase.deproxy(parentTaxon.getName(), BotanicalName.class);
463 BotanicalName constructedName = (BotanicalName)constructedHigherTaxon.getName();
464 logger.warn("handleUnequalNameCaches not yet implemented");
465 return constructedHigherTaxon;
466 }
467
468
469 /**
470 * Handles the case that the existing parent taxon and the constructed parent taxon
471 * have a diffent rank. Returns the constructedHigherTaxon if no common grand parent exists.
472 * @param parentTaxon
473 * @param constructedHigherTaxon
474 * @return
475 */
476 private Taxon handleUnequalRanks(Taxon parentTaxon, Taxon constructedHigherTaxon) {
477 BotanicalName parentName = CdmBase.deproxy(parentTaxon.getName(), BotanicalName.class);
478 BotanicalName constructedName = (BotanicalName)constructedHigherTaxon.getName();
479 int compare = compareRanks(parentName, constructedName);
480 Taxon lowerTaxon = parentTaxon;
481 Taxon grandParentTaxon = constructedHigherTaxon;
482 if (compare < 0){
483 lowerTaxon = constructedHigherTaxon;
484 grandParentTaxon = parentTaxon;
485 }
486 Taxon commonGrandParent = checkIsGrandParent(lowerTaxon, grandParentTaxon);
487 if (commonGrandParent != null){
488 if (lowerTaxon == constructedHigherTaxon){
489 //TODO merge
490 logger.warn("Merge in between taxon not yet implemented");
491 }
492 }else{
493 return constructedHigherTaxon;
494 }
495 return lowerTaxon;
496 }
497
498 /**
499 * Tries to find a taxon which matches the constructed taxon but is not a parent
500 * taxon of the constructed taxon's child (condition will not be checked).
501 * Returns null if no such taxon exists.
502 * @param constructedHigherTaxon
503 * @param state
504 * @return
505 */
506 private Taxon findExistingNonParentTaxon(CentralAfricaFernsImportState state, Taxon constructedHigherTaxon) {
507 BotanicalName constructedName = CdmBase.deproxy(constructedHigherTaxon.getName(), BotanicalName.class);
508 String titleCache = constructedName.getTitleCache();
509 String nameCache = constructedName.getNameCache();
510 UUID existingUuid = titleCacheTaxonMap.get(titleCache);
511 if (existingUuid == null){
512 existingUuid = nameCacheTaxonMap.get(nameCache);
513 }
514 Taxon relatedTaxon = null;
515 if (existingUuid != null){
516 relatedTaxon = state.getRelatedObject(HIGHER_TAXON_NAMESPACE, nameCache, Taxon.class);
517 if (relatedTaxon == null){
518 //TODO find for partition
519 relatedTaxon = (Taxon)getTaxonService().find(existingUuid);
520 if (relatedTaxon == null){
521 logger.info(state.getTaxonNumber() + " - Could not find existing name ("+nameCache+") in related objects map");
522 }else{
523 state.addRelatedObject(HIGHER_TAXON_NAMESPACE, nameCache, relatedTaxon);
524 }
525 }
526 }
527 return relatedTaxon;
528 }
529
530 /**
531 * Checks if a taxon is a grand parent of another taxon
532 * @param lowerTaxon
533 * @param higherTaxon
534 * @return
535 */
536 private Taxon checkIsGrandParent(Taxon childTaxon, Taxon grandParentTaxon) {
537 BotanicalName lowerName = CdmBase.deproxy(childTaxon.getName(), BotanicalName.class);
538 BotanicalName higherName = CdmBase.deproxy(grandParentTaxon.getName(), BotanicalName.class);
539
540 //TODO was wenn lowerTaxon constructed ist
541 logger.warn("checkIsGrandParent not yet fully implemented");
542 Taxon nextParent = getParent(childTaxon);
543 if (namesMatch(nextParent, grandParentTaxon)){
544 //TODO which one to return? Merging ?
545 logger.warn("checkIsGrandParent(matching) not yet fully implemented");
546 return grandParentTaxon;
547 }else{
548 if (compareRanks(lowerName, higherName) >= 0){
549 return null;
550 }else{
551 return checkIsGrandParent(childTaxon, grandParentTaxon);
552 }
553 }
554 }
555
556
557 /**
558 * Checks if the name caches match.
559 * @param name1
560 * @param name2
561 * @return
562 */
563 private boolean nameCachesMatch(BotanicalName name1, BotanicalName name2) {
564 return CdmUtils.nullSafeEqual(name1.getNameCache(), name2.getNameCache());
565 }
566
567 /**
568 * Checks if the name caches of the related names match.
569 *@param taxon1
570 * @param taxon2
571 * @return
572 */
573 private boolean nameCachesMatch(Taxon taxon1, Taxon taxon2) {
574 BotanicalName name1 = CdmBase.deproxy(taxon1.getName(), BotanicalName.class);
575 BotanicalName name2 = CdmBase.deproxy(taxon2.getName(), BotanicalName.class);
576 return nameCachesMatch(name1, name2);
577 }
578
579
580 /**
581 * Checks if all authors match
582 * @param name1
583 * @param name2
584 * @return
585 */
586 private boolean authorsMatch(NonViralName<?> name1, NonViralName<?> name2) {
587 String combinationAuthor1 = name1.computeCombinationAuthorNomenclaturalTitle();
588 String combinationAuthor2 = name2.computeCombinationAuthorNomenclaturalTitle();
589 String basionymAuthor1 = name1.computeBasionymAuthorNomenclaturalTitle();
590 String basionymAuthor2 = name2.computeBasionymAuthorNomenclaturalTitle();
591 String exCombinationAuthor1 = name1.computeExCombinationAuthorNomenclaturalTitle();
592 String exCombinationAuthor2 = name2.computeExCombinationAuthorNomenclaturalTitle();
593 String exBasionymAuthor1 = name1.computeExBasionymAuthorNomenclaturalTitle();
594 String exBasionymAuthor2 = name2.computeExBasionymAuthorNomenclaturalTitle();
595 boolean result =
596 CdmUtils.nullSafeEqual(combinationAuthor1, combinationAuthor2) &&
597 CdmUtils.nullSafeEqual(basionymAuthor1, basionymAuthor2) &&
598 CdmUtils.nullSafeEqual(exCombinationAuthor1, exCombinationAuthor2) &&
599 CdmUtils.nullSafeEqual(exBasionymAuthor1, exBasionymAuthor2);
600 return result;
601 }
602
603 /**
604 * Checks if all authors of the related names match.
605 * @param taxon1
606 * @param taxon2
607 * @return
608 */
609 private boolean authorsMatch(Taxon taxon1, Taxon taxon2) {
610 BotanicalName name1 = CdmBase.deproxy(taxon1.getName(), BotanicalName.class);
611 BotanicalName name2 = CdmBase.deproxy(taxon2.getName(), BotanicalName.class);
612 return authorsMatch(name1, name2);
613 }
614
615 /**
616 * Compares ranks of 2 names.
617 * @param parentName
618 * @param constructedName
619 * @return
620 */
621 private int compareRanks(BotanicalName name1, BotanicalName name2) {
622 return name1.getRank().compareTo(name2.getRank());
623 }
624
625 /**
626 * Compares the ranks of the according names.
627 * @param taxon1
628 * @param taxon2
629 * @return
630 */
631 private int compareRanks(Taxon taxon1, Taxon taxon2) {
632 BotanicalName name1 = CdmBase.deproxy(taxon1.getName(), BotanicalName.class);
633 BotanicalName name2 = CdmBase.deproxy(taxon2.getName(), BotanicalName.class);
634 return compareRanks(name1, name2);
635 }
636
637
638
639 /**
640 * Checks if 2 names match.
641 * Current strategy: true, if ranks are equal, nameCaches match and authors match
642 * @param name1
643 * @param name2
644 * @return
645 */
646 private boolean namesMatch(BotanicalName name1, BotanicalName name2) {
647 return compareRanks(name1, name2)==0 && nameCachesMatch(name1, name2) && authorsMatch(name1, name2);
648 }
649
650 /**
651 * Checks if the according names match.
652 * @see #namesMatch(BotanicalName, BotanicalName)
653 * @param taxon1
654 * @param taxon2
655 * @return
656 */
657 private boolean namesMatch(Taxon taxon1, Taxon taxon2) {
658 BotanicalName name1 = CdmBase.deproxy(taxon1.getName(), BotanicalName.class);
659 BotanicalName name2 = CdmBase.deproxy(taxon2.getName(), BotanicalName.class);
660 return namesMatch(name1, name2);
661 }
662
663
664 /**
665 * Returns the only parent of the taxon. If not parent exists <code>null</code> is
666 * returned.
667 * TODO move to taxon class (with classification)
668 * @param child
669 * @return
670 * @throws IllegalStateException if taxon belongs to multiple states
671 */
672 private Taxon getParent(Taxon child) {
673 int countNodes = child.getTaxonNodes().size();
674 if (countNodes < 1){
675 return null;
676 }else if (countNodes > 1){
677 throw new IllegalStateException("Multiple nodes exist for child taxon. This is an invalid state for this import.");
678 }else{
679 TaxonNode childNode = child.getTaxonNodes().iterator().next();
680 TaxonNode parentNode = childNode.getParent();
681 if (parentNode != null){
682 return parentNode.getTaxon();
683 }else{
684 return null;
685 }
686 }
687 }
688
689
690 /**
691 * Persists and saves the newly created taxon to the CDM store and to the look-up
692 * maps.
693 * @param state
694 * @param constructedHigherTaxon
695 * @return
696 */
697 private Taxon saveConstructedTaxon(CentralAfricaFernsImportState state, Taxon constructedHigherTaxon) {
698 BotanicalName constructedName = CdmBase.deproxy(constructedHigherTaxon.getName(), BotanicalName.class);
699 String nameCache = constructedName.getNameCache();
700 String titleCache = constructedName.getTitleCache();
701 nameCacheTaxonMap.put(nameCache, constructedHigherTaxon.getUuid());
702 titleCacheTaxonMap.put(titleCache, constructedHigherTaxon.getUuid());
703 state.addRelatedObject(HIGHER_TAXON_NAMESPACE, nameCache, constructedHigherTaxon);
704
705 //persist
706 // Reference citation = state.getConfig().getSourceReference(); //throws nonUniqueObject exception
707 Reference citation = null;
708 String id = state.getTaxonNumber() + "-" + constructedName.getRank().getTitleCache();
709 addOriginalSource(constructedName, id, NAME_NAMESPACE, citation);
710 addOriginalSource(constructedHigherTaxon, id, TAXON_NAMESPACE, citation);
711 getTaxonService().save(constructedHigherTaxon);
712
713 return constructedHigherTaxon;
714 }
715
716
717 //TODO use Mapper
718 /**
719 * Adds the parent child relationship. Creates and saves the classification if needed.
720 * Adds parent and child to the classification.
721 * @param state
722 * @param treeRefFk
723 * @param child
724 * @param parent
725 * @param citation
726 * @param microCitation
727 * @return
728 */
729 private boolean makeTaxonomicallyIncluded(CentralAfricaFernsImportState state, Integer treeRefFk, Taxon child, Taxon parent, Reference citation, String microCitation){
730 String treeKey;
731 UUID treeUuid;
732 if (treeRefFk == null){
733 treeKey = "1"; // there is only one tree and it gets the map key '1'
734 treeUuid = state.getConfig().getClassificationUuid();
735 }else{
736 treeKey =String.valueOf(treeRefFk);
737 treeUuid = state.getTreeUuidByTreeKey(treeKey);
738 }
739 Classification tree = (Classification)state.getRelatedObject(DbImportTaxIncludedInMapper.TAXONOMIC_TREE_NAMESPACE, treeKey);
740 if (tree == null){
741 IClassificationService service = state.getCurrentIO().getClassificationService();
742 tree = service.find(treeUuid);
743 if (tree == null){
744 String treeName = state.getConfig().getClassificationName();
745 tree = Classification.NewInstance(treeName);
746 tree.setUuid(treeUuid);
747 //FIXME tree reference
748 tree.setReference(citation);
749 service.save(tree);
750 }
751 state.addRelatedObject(DbImportTaxIncludedInMapper.TAXONOMIC_TREE_NAMESPACE, treeKey, tree);
752 }
753
754 TaxonNode childNode;
755 if (parent != null){
756 childNode = tree.addParentChild(parent, child, citation, microCitation);
757 }else{
758 childNode = tree.addChildTaxon(child, citation, microCitation, null);
759 }
760 return (childNode != null);
761 }
762
763
764 /**
765 * Reasons if a higher taxon should exist. If it should exist it returns it as a new taxon.
766 * Returns null otherwise.
767 * @return
768 * @throws SQLException
769 */
770 private Taxon constructNextHigherTaxon(CentralAfricaFernsImportState state, ResultSet rs, Taxon childTaxon, Epithets epithets) throws SQLException {
771
772 Taxon result = null;
773 BotanicalName childName = CdmBase.deproxy(childTaxon.getName(), BotanicalName.class);
774 Rank childRank = childName.getRank();
775 BotanicalName higherName;
776 higherName = handleInfraSpecific(childRank, epithets);
777 if (higherName.getRank() == null){
778 handleSpecies(childRank, higherName, epithets);
779 }
780 if (higherName.getRank() == null){
781 handleInfraGeneric(childRank, higherName, epithets);
782 }
783 if (higherName.getRank() == null){
784 handleUninomial(childRank, higherName, epithets);
785 }
786
787 if (higherName.getRank() != null){
788 result = Taxon.NewInstance(higherName, childTaxon.getSec());
789 //TODO correct??
790 setAuthor(higherName, rs, state.getTaxonNumber(), true);
791 // UUID uuid = higherName.getUuid();
792 // String name = higherName.getNameCache();
793 // taxonMap.put(name, uuid);
794 // state.addRelatedObject(HIGHER_TAXON_NAMESPACE, higherName.getNameCache(), result);
795 }
796 return result;
797 }
798
799 private BotanicalName handleInfraSpecific(Rank lowerTaxonRank, Epithets epithets) {
800
801 BotanicalName taxonName = BotanicalName.NewInstance(null);
802 Rank newRank = null;
803
804 if (StringUtils.isNotBlank(epithets.subFormaName) && lowerTaxonRank.isLower(Rank.SUBFORM())){
805 taxonName.setInfraSpecificEpithet(epithets.subFormaName);
806 newRank = Rank.SUBFORM();
807 }else if (StringUtils.isNotBlank(epithets.formaName) && lowerTaxonRank.isLower(Rank.FORM())){
808 taxonName.setInfraSpecificEpithet(epithets.formaName);
809 newRank = Rank.FORM();
810 }else if (StringUtils.isNotBlank(epithets.subVariety) && lowerTaxonRank.isLower(Rank.SUBVARIETY())){
811 taxonName.setInfraSpecificEpithet(epithets.subVariety);
812 newRank = Rank.SUBVARIETY();
813 }else if (StringUtils.isNotBlank(epithets.varietyName) && lowerTaxonRank.isLower(Rank.VARIETY())){
814 taxonName.setInfraSpecificEpithet(epithets.varietyName);
815 newRank = Rank.VARIETY();
816 }else if (StringUtils.isNotBlank(epithets.subspeciesName) && lowerTaxonRank.isLower(Rank.SUBSPECIES())){
817 taxonName.setInfraSpecificEpithet(epithets.subspeciesName);
818 newRank = Rank.SUBSPECIES();
819 }
820
821 if (newRank != null){
822 taxonName.setSpecificEpithet(epithets.specificEpithet);
823 taxonName.setGenusOrUninomial(epithets.genusName);
824 taxonName.setRank(newRank);
825 }
826
827 return taxonName;
828 }
829
830 private BotanicalName handleSpecies(Rank lowerTaxonRank, BotanicalName taxonName, Epithets epithets) {
831 Rank newRank = null;
832
833 if (StringUtils.isNotBlank(epithets.specificEpithet) && lowerTaxonRank.isLower(Rank.SPECIES())){
834 taxonName.setSpecificEpithet(epithets.specificEpithet);
835 newRank = Rank.SPECIES();
836 }
837 if (newRank != null){
838 taxonName.setGenusOrUninomial(epithets.genusName);
839 taxonName.setRank(newRank);
840 }
841 return taxonName;
842 }
843
844 private BotanicalName handleInfraGeneric(Rank lowerTaxonRank, BotanicalName taxonName, Epithets epithets) {
845 Rank newRank = null;
846
847 if (StringUtils.isNotBlank(epithets.seriesName) && lowerTaxonRank.isLower(Rank.SERIES())){
848 taxonName.setInfraGenericEpithet(epithets.seriesName);
849 newRank = Rank.SERIES();
850 }else if (StringUtils.isNotBlank(epithets.subsectionName) && lowerTaxonRank.isLower(Rank.SUBSECTION_BOTANY())){
851 taxonName.setInfraGenericEpithet(epithets.subsectionName);
852 newRank = Rank.SUBSECTION_BOTANY();
853 }else if (StringUtils.isNotBlank(epithets.sectionName) && lowerTaxonRank.isLower(Rank.SECTION_BOTANY())){
854 taxonName.setInfraGenericEpithet(epithets.sectionName);
855 newRank = Rank.SECTION_BOTANY();
856 }else if (StringUtils.isNotBlank(epithets.subGenusName) && lowerTaxonRank.isLower(Rank.SUBGENUS())){
857 taxonName.setInfraGenericEpithet(epithets.subGenusName);
858 newRank = Rank.SUBGENUS();
859 }
860 if (newRank != null){
861 taxonName.setGenusOrUninomial(epithets.genusName);
862 taxonName.setRank(newRank);
863 }
864 return taxonName;
865 }
866
867
868
869 private BotanicalName handleUninomial(Rank lowerTaxonRank, BotanicalName taxonName, Epithets epithets) {
870
871 Rank newRank = null;
872 if (StringUtils.isNotBlank(epithets.genusName) && lowerTaxonRank.isLower(Rank.GENUS())){
873 taxonName.setGenusOrUninomial(epithets.genusName);
874 newRank = Rank.GENUS();
875 }else if (StringUtils.isNotBlank(epithets.subTribusName) && lowerTaxonRank.isLower(Rank.SUBTRIBE())){
876 taxonName.setGenusOrUninomial(epithets.subTribusName);
877 newRank = Rank.SUBTRIBE();
878 }else if (StringUtils.isNotBlank(epithets.tribusName) && lowerTaxonRank.isLower(Rank.TRIBE())){
879 taxonName.setGenusOrUninomial(epithets.tribusName);
880 newRank = Rank.TRIBE();
881 }else if (StringUtils.isNotBlank(epithets.subFamilyName) && lowerTaxonRank.isLower(Rank.SUBFAMILY())){
882 taxonName.setGenusOrUninomial(epithets.subFamilyName);
883 newRank = Rank.SUBFAMILY();
884 }else if (StringUtils.isNotBlank(epithets.familyName) && lowerTaxonRank.isLower(Rank.FAMILY())){
885 taxonName.setGenusOrUninomial(epithets.familyName);
886 newRank = Rank.FAMILY();
887 }else if (StringUtils.isNotBlank(epithets.subOrderName) && lowerTaxonRank.isLower(Rank.SUBORDER())){
888 taxonName.setGenusOrUninomial(epithets.subOrderName);
889 newRank = Rank.SUBORDER();
890 }else if (StringUtils.isNotBlank(epithets.orderName) && lowerTaxonRank.isLower(Rank.ORDER())){
891 taxonName.setGenusOrUninomial(epithets.orderName);
892 newRank = Rank.ORDER();
893 }
894 taxonName.setRank(newRank);
895 return taxonName;
896 }
897
898
899 /**
900 * for internal use only, used by MethodMapper
901 */
902 private TaxonBase mapCommonName(ResultSet rs, CentralAfricaFernsImportState state) throws SQLException{
903 String taxonNumber = state.getTaxonNumber();
904 String commonNames = rs.getString("Common names");
905 TaxonBase<?> taxonBase = state.getRelatedObject(state.CURRENT_OBJECT_NAMESPACE, state.CURRENT_OBJECT_ID, TaxonBase.class);
906 if (StringUtils.isNotBlank(commonNames)){
907 Taxon taxon = getAcceptedTaxon(taxonBase);
908 if ( taxon != null ){
909 TaxonDescription description = getTaxonDescription(taxon, false, true);
910 String[] split = commonNames.split(",");
911 for (String commonNameString: split){
912 CommonTaxonName commonName = CommonTaxonName.NewInstance(commonNameString.trim(), Language.ENGLISH());
913 description.addElement(commonName);
914 }
915 }else{
916 logger.warn(taxonNumber + " - Accepted taxon for synonym can't be defined for common name. Synonym " + taxonBase.getName().getTitleCache());
917 }
918 }
919 return taxonBase;
920 }
921
922
923 /**
924 * for internal use only, used by MethodMapper
925 */
926 private TaxonBase mapDistribution(ResultSet rs, CentralAfricaFernsImportState state) throws SQLException{
927 try {
928 String taxonNumber = state.getTaxonNumber();
929 // logger.info(taxonNumber);
930 TaxonBase<?> taxonBase = state.getRelatedObject(state.CURRENT_OBJECT_NAMESPACE, state.CURRENT_OBJECT_ID, TaxonBase.class);
931 String countriesString = rs.getString("Distribution - Country");
932 String province = rs.getString("Distribution - Province");
933 String distributionDetailed = rs.getString("Distribution - detailed");
934 if (taxonBase != null){
935 TaxonNameBase nameUsedInSource = taxonBase.getName();
936 Taxon taxon = getAcceptedTaxon(taxonBase);
937 if (taxon != null){
938
939 if (StringUtils.isNotBlank(countriesString) ){
940 makeCountries(state, taxonNumber, taxon, nameUsedInSource, countriesString, province, distributionDetailed);
941 }
942 makeProvince(taxon, province);
943 makeDistributionDetailed(taxon, distributionDetailed);
944 }else{
945 logger.warn(taxonNumber + " - Accepted taxon for synonym can't be defined for distribution. Synonym " + taxonBase.getName().getTitleCache());
946 }
947 }else{
948 logger.warn(" - " + taxonNumber + ": TaxonBase was null");
949 }
950 return taxonBase;
951 } catch (Exception e) {
952 e.printStackTrace();
953 return null;
954 }
955 }
956
957
958 /**
959 * for internal use only, used by MethodMapper
960 * @param commonNames
961 */
962 private TaxonBase mapEcology(ResultSet rs, CentralAfricaFernsImportState state) throws SQLException{
963 String taxonNumber = state.getTaxonNumber();
964 String ecologyString = rs.getString("Ecology");
965 TaxonBase<?> taxonBase = state.getRelatedObject(state.CURRENT_OBJECT_NAMESPACE, state.CURRENT_OBJECT_ID, TaxonBase.class);
966 if (StringUtils.isNotBlank(ecologyString)){
967 Taxon taxon = getAcceptedTaxon(taxonBase);
968
969 if (taxon != null){
970 TaxonDescription description = getTaxonDescription(taxon, false, true);
971 TextData ecology = TextData.NewInstance(Feature.ECOLOGY());
972 ecology.putText(Language.ENGLISH(), ecologyString.trim());
973 description.addElement(ecology);
974 }else{
975 logger.warn(taxonNumber + " - Accepted taxon for synonym can't be defined for ecology. Synonym " + taxonBase.getName().getTitleCache());
976 }
977 }
978 return taxonBase;
979 }
980
981
982
983
984 private void makeDistributionDetailed(Taxon taxon, String distributionDetailed) {
985 if (StringUtils.isNotBlank(distributionDetailed)){
986 TaxonDescription description = getTaxonDescription(taxon, false, true);
987 TextData distribution = TextData.NewInstance(Feature.DISTRIBUTION());
988 description.addElement(distribution);
989 distribution.putText(Language.ENGLISH(), distributionDetailed);
990 }
991 }
992
993
994 private void makeProvince(Taxon taxon, String province) {
995 if (StringUtils.isNotBlank(province)){
996 TaxonDescription description = getTaxonDescription(taxon, false, true);
997 TextData distribution = TextData.NewInstance(Feature.DISTRIBUTION());
998 description.addElement(distribution);
999 distribution.putText(Language.ENGLISH(), province);
1000 }
1001 }
1002
1003
1004 /**
1005 * @param state
1006 * @param taxonNumber
1007 * @param taxonBase
1008 * @param countriesString
1009 */
1010 private void makeCountries(CentralAfricaFernsImportState state, String taxonNumber, Taxon taxon, TaxonNameBase nameUsedInSource, String countriesString, String province, String distributionDetailed) {
1011 countriesString = countriesString.replaceAll("\\*", "");
1012 countriesString = countriesString.replace(" ", " ");
1013 countriesString = countriesString.replace(", endemic", " - endemic");
1014 countriesString = countriesString.replace("(endemic)", " - endemic");
1015 countriesString = countriesString.replace("(introduced)", " - introduced");
1016 countriesString = countriesString.replace("(naturalised)", " - naturalised");
1017 countriesString = countriesString.replace("Madagascar-", "Madagascar -");
1018 countriesString = countriesString.replace("Mahé", "Mahe");
1019
1020 String[] split = countriesString.split("[,;]");
1021 String remainingString = null;
1022 for (String countryString : split){
1023 countryString = CdmUtils.concat(", ", remainingString , countryString);
1024 if (countryString.matches(".*\\(.*") && ! countryString.matches(".*\\).*")){
1025 remainingString = countryString;
1026 continue;
1027 }
1028 remainingString = null;
1029 try {
1030 makeSingleCountry(state, taxonNumber, taxon, nameUsedInSource, countryString.trim());
1031 } catch (UndefinedTransformerMethodException e) {
1032 e.printStackTrace();
1033 }
1034 }
1035 }
1036
1037
1038 private void makeSingleCountry(CentralAfricaFernsImportState state, String taxonNumber, Taxon taxon, TaxonNameBase nameUsedInSource, String country) throws UndefinedTransformerMethodException {
1039 boolean areaDoubtful = false;
1040 Distribution distribution = Distribution.NewInstance(null, PresenceTerm.PRESENT());
1041 Reference sourceReference = this.sourceReference;
1042 distribution.addSource(taxonNumber, "Distribution_Country", sourceReference, null, nameUsedInSource, null);
1043 NamedArea area = null;
1044 //empty
1045 if (StringUtils.isBlank(country)){
1046 return;
1047 }
1048 country = country.trim();
1049 //doubtful
1050 if (country.startsWith("?")){
1051 areaDoubtful = true;
1052 country = country.substring(1).trim();
1053 }
1054 //status
1055 country = makeCountryStatus(state, country, distribution);
1056
1057 //brackets
1058 country = makeCountryBrackets(state, taxonNumber, taxon, nameUsedInSource, country);
1059 String countryWithoutIslands = null;
1060 String countryWithoutDot = null;
1061 if (country.endsWith(" Isl.") || country.endsWith(" isl.") ){
1062 countryWithoutIslands = country.substring(0, country.length()-5);
1063 }
1064 if (country.endsWith(".")){
1065 countryWithoutDot = country.substring(0, country.length()-1);
1066 }
1067 if (country.endsWith("*")){
1068 country = country.substring(0, country.length()-1);
1069 }
1070 if (country.endsWith("Islands")){
1071 country = country.replace("Islands", "Is.");
1072 }
1073
1074
1075 //areas
1076 if (TdwgArea.isTdwgAreaLabel(country)){
1077 //tdwg
1078 area = TdwgArea.getAreaByTdwgLabel(country);
1079 }else if (TdwgArea.isTdwgAreaLabel(countryWithoutIslands)){
1080 //tdwg
1081 area = TdwgArea.getAreaByTdwgLabel(countryWithoutIslands);
1082 }else if (TdwgArea.isTdwgAreaLabel(countryWithoutDot)){
1083 //tdwg
1084 area = TdwgArea.getAreaByTdwgLabel(countryWithoutDot);
1085 }else if ( (area = state.getTransformer().getNamedAreaByKey(country)) != null) {
1086 //area already set
1087 }else if (WaterbodyOrCountry.isWaterbodyOrCountryLabel(country)){
1088 //iso
1089 area = WaterbodyOrCountry.getWaterbodyOrCountryByLabel(country);
1090 }else{
1091 //others
1092 NamedAreaLevel level = null;
1093 NamedAreaType areaType = null;
1094
1095 UUID uuid = state.getTransformer().getNamedAreaUuid(country);
1096 if (uuid == null){
1097 logger.error(taxonNumber + " - Unknown country: " + country);
1098 }
1099 area = getNamedArea(state, uuid, country, country, country, areaType, level);
1100 }
1101
1102 distribution.setArea(area);
1103 if (areaDoubtful == true){
1104 if (distribution.getStatus().equals(PresenceTerm.PRESENT())){
1105 distribution.setStatus(PresenceTerm.PRESENT_DOUBTFULLY());
1106 }
1107 }
1108 TaxonDescription description = getTaxonDescription(taxon, false, true);
1109 description.addElement(distribution);
1110 }
1111
1112
1113
1114 /**
1115 * @param state
1116 * @return
1117 */
1118 Reference sourceReference = null;
1119 private Reference getFernsSourceReference(CentralAfricaFernsImportState state) {
1120 // if (sourceReference == null || true){
1121 Reference tmpReference = state.getConfig().getSourceReference();
1122 sourceReference = getReferenceService().find(tmpReference.getUuid());
1123 // }
1124 return sourceReference;
1125 }
1126
1127
1128 private String makeCountryBrackets(CentralAfricaFernsImportState state, String taxonNumber, Taxon taxon, TaxonNameBase nameUsedInSource, String country) {
1129 String[] split = (country + " ").split("\\(.*\\)");
1130 if (split.length == 2){
1131 String bracket = country.substring(split[0].length()+1, country.indexOf(")"));
1132 country = split[0].trim();
1133 makeCountries(state, taxonNumber, taxon, nameUsedInSource, bracket, null, null);
1134 }else if (split.length ==1){
1135 //do nothing
1136 }else{
1137 logger.warn("Illegal length");
1138 }
1139 return country;
1140 }
1141
1142 private String makeCountryStatus(CentralAfricaFernsImportState state, String country, Distribution distribution) throws UndefinedTransformerMethodException {
1143 PresenceTerm status = null;
1144 String[] split = country.split(" - ");
1145
1146 if (split.length == 2){
1147 country = split[0].trim();
1148 String statusString = split[1];
1149 statusString = statusString.replace(".", "");
1150 status = state.getTransformer().getPresenceTermByKey(statusString);
1151 if (status == null){
1152 logger.warn("No status found: "+ statusString);
1153 }
1154 // UUID uuid = null;
1155 // status = getPresenceTerm(state, uuid, statusString, statusString, null);
1156 }else if (split.length == 1){
1157 //nothing to do
1158 }else{
1159 logger.warn("Invalid length: " + split.length);
1160 }
1161 if (status != null){
1162 distribution.setStatus(status);
1163 }
1164 return country;
1165 }
1166
1167
1168
1169
1170 /* (non-Javadoc)
1171 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IoStateBase)
1172 */
1173 @Override
1174 protected boolean doCheck(CentralAfricaFernsImportState state){
1175 IOValidator<CentralAfricaFernsImportState> validator = new CentralAfricaFernsTaxonImportValidator();
1176 return validator.validate(state);
1177 }
1178
1179 /* (non-Javadoc)
1180 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IoStateBase)
1181 */
1182 @Override
1183 protected boolean isIgnore(CentralAfricaFernsImportState state){
1184 return ! state.getConfig().isDoRelTaxa();
1185 }
1186
1187
1188
1189 //************************ OLD **********************************************************
1190
1191 /**
1192 * Adds the higherTaxon authors to the existingHigherTaxon authors if the higherTaxon has authors and
1193 * the existingHigherTaxon has no authors.
1194 * Returns false if both taxa have authors and the authors differ from each other.
1195 * @param higherTaxon
1196 * @param existingHigherTaxon
1197 */
1198 private boolean mergeAuthors_old(Taxon higherTaxon, Taxon existingHigherTaxon) {
1199 NonViralName existingName = CdmBase.deproxy(higherTaxon.getName(), NonViralName.class);
1200 NonViralName newName = CdmBase.deproxy(existingHigherTaxon.getName(), NonViralName.class);
1201 if (existingName == newName){
1202 return true;
1203 }
1204 if (! newName.hasAuthors()){
1205 return true;
1206 }
1207 if (! existingName.hasAuthors()){
1208 existingName.setCombinationAuthorTeam(newName.getCombinationAuthorTeam());
1209 existingName.setExCombinationAuthorTeam(newName.getExCombinationAuthorTeam());
1210 existingName.setBasionymAuthorTeam(newName.getBasionymAuthorTeam());
1211 existingName.setExBasionymAuthorTeam(newName.getExBasionymAuthorTeam());
1212 return true;
1213 }
1214 boolean authorsAreSame = true;
1215 authorsAreSame &= getNomTitleNz(existingName.getCombinationAuthorTeam()).equals(getNomTitleNz(newName.getCombinationAuthorTeam()));
1216 authorsAreSame &= getNomTitleNz(existingName.getExCombinationAuthorTeam()).equals(getNomTitleNz(newName.getExCombinationAuthorTeam()));
1217 authorsAreSame &= getNomTitleNz(existingName.getBasionymAuthorTeam()).equals(getNomTitleNz(newName.getBasionymAuthorTeam()));
1218 authorsAreSame &= getNomTitleNz(existingName.getExBasionymAuthorTeam()).equals(getNomTitleNz(newName.getExBasionymAuthorTeam()));
1219 return authorsAreSame;
1220
1221
1222 }
1223
1224 /**
1225 * Returns the nomenclatural title of the author. Returns empty string if author is <code>null</code> or
1226 * titleCache is <code>null</code>.
1227 * @param author
1228 * @return
1229 */
1230 private String getNomTitleNz(INomenclaturalAuthor author) {
1231 if (author != null){
1232 return CdmUtils.Nz(author.getNomenclaturalTitle());
1233 }else{
1234 return "";
1235 }
1236 }
1237
1238 private Taxon getExistingHigherTaxon_old(Taxon child, Taxon higherTaxon) {
1239 int countNodes = child.getTaxonNodes().size();
1240 if (countNodes < 1){
1241 return null;
1242 }else if (countNodes > 1){
1243 throw new IllegalStateException("Multiple nodes exist for child taxon. This is an invalid state.");
1244 }else{
1245 TaxonNode childNode = child.getTaxonNodes().iterator().next();
1246 TaxonNode parentNode = childNode.getParent();
1247 if (parentNode != null){
1248 String existingParentTitle = parentNode.getTaxon().getName().getTitleCache();
1249 String newParentTitle = higherTaxon.getName().getTitleCache();
1250 if (existingParentTitle.equals(newParentTitle)){
1251 return parentNode.getTaxon();
1252 }
1253 }
1254 return null;
1255 }
1256 }
1257
1258
1259
1260 /**
1261 * Tests if this the child taxon already is a child of the higher taxon.
1262 * @param child
1263 * @param higherTaxon
1264 * @return
1265 */
1266 private boolean includedRelationshipExists_Old(Taxon child, Taxon higherTaxon) {
1267 int countNodes = higherTaxon.getTaxonNodes().size();
1268 if (countNodes < 1){
1269 return false;
1270 }else if (countNodes > 1){
1271 throw new IllegalStateException("Multiple nodes exist for higher taxon. This is an invalid state.");
1272 }else{
1273 TaxonNode higherNode = higherTaxon.getTaxonNodes().iterator().next();
1274 return childExists_old(child, higherNode);
1275 }
1276 }
1277
1278
1279
1280 private boolean childExists_old(Taxon child, TaxonNode higherNode) {
1281 for (TaxonNode childNode : higherNode.getChildNodes()){
1282 String existingChildTitle = childNode.getTaxon().getName().getTitleCache();
1283 String newChildTitle = child.getName().getTitleCache();
1284 if (existingChildTitle.equals(newChildTitle)){
1285 return true;
1286 }
1287 }
1288 return false;
1289 }
1290
1291
1292 }