2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.cdm
.io
.excel
.taxa
;
12 import java
.net
.MalformedURLException
;
14 import java
.net
.URISyntaxException
;
15 import java
.util
.Arrays
;
16 import java
.util
.HashMap
;
17 import java
.util
.HashSet
;
18 import java
.util
.List
;
21 import java
.util
.UUID
;
23 import org
.apache
.commons
.lang
.StringUtils
;
24 import org
.apache
.log4j
.Logger
;
25 import org
.springframework
.stereotype
.Component
;
27 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
28 import eu
.etaxonomy
.cdm
.io
.excel
.common
.ExcelRowBase
.SourceDataHolder
;
29 import eu
.etaxonomy
.cdm
.model
.agent
.Team
;
30 import eu
.etaxonomy
.cdm
.model
.agent
.TeamOrPersonBase
;
31 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
32 import eu
.etaxonomy
.cdm
.model
.common
.DescriptionElementSource
;
33 import eu
.etaxonomy
.cdm
.model
.common
.Extension
;
34 import eu
.etaxonomy
.cdm
.model
.common
.ExtensionType
;
35 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
36 import eu
.etaxonomy
.cdm
.model
.common
.TimePeriod
;
37 import eu
.etaxonomy
.cdm
.model
.description
.CommonTaxonName
;
38 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
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
.TaxonNameDescription
;
44 import eu
.etaxonomy
.cdm
.model
.description
.TextData
;
45 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
46 import eu
.etaxonomy
.cdm
.model
.location
.TdwgArea
;
47 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
48 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalCode
;
49 import eu
.etaxonomy
.cdm
.model
.name
.NonViralName
;
50 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
51 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
52 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
53 import eu
.etaxonomy
.cdm
.model
.reference
.ReferenceFactory
;
54 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
55 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
56 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationshipType
;
57 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
58 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
59 import eu
.etaxonomy
.cdm
.strategy
.exceptions
.StringNotParsableException
;
60 import eu
.etaxonomy
.cdm
.strategy
.exceptions
.UnknownCdmTypeException
;
61 import eu
.etaxonomy
.cdm
.strategy
.parser
.NonViralNameParserImpl
;
64 * @author a.babadshanjan
69 public class NormalExplicitImport
extends TaxonExcelImporterBase
{
70 private static final Logger logger
= Logger
.getLogger(NormalExplicitImport
.class);
72 public static Set
<String
> validMarkers
= new HashSet
<String
>(Arrays
.asList(new String
[]{"", "valid", "accepted", "a", "v", "t"}));
73 public static Set
<String
> synonymMarkers
= new HashSet
<String
>(Arrays
.asList(new String
[]{"", "invalid", "synonym", "s", "i"}));
74 public static final UUID uuidRefExtension
= UUID
.fromString("a46533df-7a78-448f-9b80-36d087fbdf2a");
77 * @see eu.etaxonomy.cdm.io.excel.common.ExcelTaxonOrSpecimenImportBase#analyzeSingleValue(eu.etaxonomy.cdm.io.excel.common.ExcelTaxonOrSpecimenImportBase.KeyValue, eu.etaxonomy.cdm.io.excel.common.ExcelImportState)
80 protected void analyzeSingleValue(KeyValue keyValue
, TaxonExcelImportState state
) {
82 NormalExplicitRow normalExplicitRow
= state
.getCurrentRow();
83 String key
= keyValue
.key
;
84 String value
= keyValue
.value
;
85 Integer index
= keyValue
.index
;
86 if (key
.equalsIgnoreCase(ID_COLUMN
)) {
87 int ivalue
= floatString2IntValue(value
);
88 normalExplicitRow
.setId(ivalue
);
90 } else if(key
.equalsIgnoreCase(PARENT_ID_COLUMN
)) {
91 int ivalue
= floatString2IntValue(value
);
92 normalExplicitRow
.setParentId(ivalue
);
94 } else if(key
.equalsIgnoreCase(RANK_COLUMN
)) {
95 normalExplicitRow
.setRank(value
);
97 } else if(key
.equalsIgnoreCase(SCIENTIFIC_NAME_COLUMN
)) {
98 normalExplicitRow
.setScientificName(value
);
100 } else if(key
.equalsIgnoreCase(AUTHOR_COLUMN
)) {
101 normalExplicitRow
.setAuthor(value
);
103 } else if(key
.equalsIgnoreCase(NAME_STATUS_COLUMN
)) {
104 normalExplicitRow
.setNameStatus(value
);
106 } else if(key
.equalsIgnoreCase(VERNACULAR_NAME_COLUMN
)) {
107 normalExplicitRow
.setCommonName(value
);
109 } else if(key
.equalsIgnoreCase(LANGUAGE_COLUMN
)) {
110 normalExplicitRow
.setLanguage(value
);
112 } else if(key
.equalsIgnoreCase(TDWG_COLUMN
)) {
113 //TODO replace still necessary?
114 value
= value
.replace(".0", "");
115 normalExplicitRow
.putDistribution(index
, value
);
117 } else if(key
.equalsIgnoreCase(PROTOLOGUE_COLUMN
)) {
118 normalExplicitRow
.putProtologue(index
, value
);
120 } else if(key
.equalsIgnoreCase(IMAGE_COLUMN
)) {
121 normalExplicitRow
.putImage(index
, value
);
124 if (analyzeFeatures(state
, keyValue
)){
127 String message
= "Unexpected column header " + key
;
128 fireWarningEvent(message
, state
, 10);
129 state
.setUnsuccessfull();
130 logger
.error(message
);
138 * Create base taxa and add all information attached to it's name.
141 protected void firstPass(TaxonExcelImportState state
) {
146 // System.out.println("FP:" + state.getCurrentLine());
148 NormalExplicitRow taxonDataHolder
= state
.getCurrentRow();
150 String rankStr
= taxonDataHolder
.getRank();
151 String taxonNameStr
= taxonDataHolder
.getScientificName();
152 String authorStr
= taxonDataHolder
.getAuthor();
153 String nameStatus
= taxonDataHolder
.getNameStatus();
154 Integer id
= taxonDataHolder
.getId();
155 UUID cdmUuid
= taxonDataHolder
.getCdmUuid();
157 TaxonBase
<?
> taxonBase
= null;
158 if (cdmUuid
!= null){
159 taxonBase
= getTaxonService().find(cdmUuid
);
161 if (CdmUtils
.isNotEmpty(taxonNameStr
)) {
165 rank
= Rank
.getRankByNameOrAbbreviation(rankStr
);
166 } catch (UnknownCdmTypeException ex
) {
168 rank
= Rank
.getRankByEnglishName(rankStr
, state
.getConfig().getNomenclaturalCode(), false);
169 } catch (UnknownCdmTypeException e
) {
170 state
.setUnsuccessfull();
171 logger
.error(rankStr
+ " is not a valid rank.");
176 taxonBase
= createTaxon(state
, rank
, taxonNameStr
, authorStr
, nameStatus
);
181 if (taxonBase
== null){
182 String message
= "Taxon could not be created. Record will not be handled";
183 fireWarningEvent(message
, "Record: " + state
.getCurrentLine(), 6);
184 logger
.warn(message
);
185 state
.setUnsuccessfull();
190 for (String protologue
: taxonDataHolder
.getProtologues()){
191 TextData textData
= TextData
.NewInstance(Feature
.PROTOLOGUE());
192 this.getNameDescription(taxonBase
.getName()).addElement(textData
);
195 uri
= new URI(protologue
);
196 textData
.addMedia(Media
.NewInstance(uri
, null, null, null));
197 } catch (URISyntaxException e
) {
198 String warning
= "URISyntaxException when trying to convert to URI: " + protologue
;
199 logger
.error(warning
);
200 state
.setUnsuccessfull();
204 state
.putTaxon(id
, taxonBase
);
205 getTaxonService().save(taxonBase
);
213 * Stores parent-child, synonym and common name relationships.
214 * Adds all taxon related descriptive information (this is not done in the first pass
215 * because the information may also be attached to a synonym).
218 protected void secondPass(TaxonExcelImportState state
) {
219 System
.out
.println(state
.getCurrentLine());
221 NormalExplicitRow taxonDataHolder
= state
.getCurrentRow();
222 String taxonNameStr
= taxonDataHolder
.getScientificName();
223 String nameStatus
= taxonDataHolder
.getNameStatus();
224 String commonNameStr
= taxonDataHolder
.getCommonName();
225 Integer parentId
= taxonDataHolder
.getParentId();
226 Integer childId
= taxonDataHolder
.getId();
227 UUID cdmUuid
= taxonDataHolder
.getCdmUuid();
229 TaxonNameBase
<?
,?
> nameUsedInSource
;
231 if (cdmUuid
!= null){
232 TaxonBase
<?
> taxonBase
= getTaxonService().find(cdmUuid
);
233 acceptedTaxon
= getAcceptedTaxon(taxonBase
);
234 nameUsedInSource
= taxonBase
.getName();
236 //TODO error handling for class cast
237 Taxon parentTaxon
= CdmBase
.deproxy(state
.getTaxonBase(parentId
), Taxon
.class);
238 if (CdmUtils
.isNotEmpty(taxonNameStr
)) {
239 TaxonBase
<?
> taxonBase
= state
.getTaxonBase(childId
);
240 nameUsedInSource
= taxonBase
.getName();
241 nameStatus
= CdmUtils
.Nz(nameStatus
).trim().toLowerCase();
242 if (validMarkers
.contains(nameStatus
)){
243 Taxon taxon
= CdmBase
.deproxy(taxonBase
, Taxon
.class);
244 acceptedTaxon
= taxon
;
245 // Add the parent relationship
246 if (state
.getCurrentRow().getParentId() != 0) {
247 if (parentTaxon
!= null) {
248 //Taxon taxon = (Taxon)state.getTaxonBase(childId);
250 Reference
<?
> citation
= state
.getConfig().getSourceReference();
251 String microCitation
= null;
252 Taxon childTaxon
= taxon
;
253 makeParent(state
, parentTaxon
, childTaxon
, citation
, microCitation
);
254 getTaxonService().saveOrUpdate(parentTaxon
);
256 String message
= "Taxonomic parent not found for " + taxonNameStr
;
257 logger
.warn(message
);
258 fireWarningEvent(message
, state
, 6);
259 state
.setUnsuccessfull();
262 //do nothing (parent == 0) no parent exists
264 }else if (synonymMarkers
.contains(nameStatus
)){
265 //add synonym relationship
266 acceptedTaxon
= parentTaxon
;
268 Synonym synonym
= CdmBase
.deproxy(taxonBase
,Synonym
.class);
269 if (acceptedTaxon
== null){
270 String message
= "Accepted/valid taxon could not be found. Please check referential integrity.";
271 fireWarningEvent(message
, state
, 8);
273 acceptedTaxon
.addSynonym(synonym
, SynonymRelationshipType
.SYNONYM_OF());
274 getTaxonService().saveOrUpdate(acceptedTaxon
);
276 } catch (Exception e
) {
277 String message
= "Unhandled exception (%s) occurred during synonym import/update";
278 message
= String
.format(message
, e
.getMessage());
279 fireWarningEvent(message
, state
, 10);
280 state
.setUnsuccessfull();
283 acceptedTaxon
= null;
284 String message
= "Unhandled name status (%s)";
285 message
= String
.format(message
, nameStatus
);
286 fireWarningEvent(message
, state
, 8);
288 }else{//taxonNameStr is empty
289 //vernacular name case
290 acceptedTaxon
= parentTaxon
;
291 nameUsedInSource
= null;
295 if (acceptedTaxon
== null && (CdmUtils
.isNotEmpty(commonNameStr
) ||taxonDataHolder
.getFeatures().size() > 0 )){
296 String message
= "Accepted taxon could not be found. Can't add additional data (common names, descriptive data, ...) to taxon";
297 fireWarningEvent(message
, state
, 6);
300 if (CdmUtils
.isNotEmpty(commonNameStr
)){ // add common name to taxon
301 handleCommonName(state
, taxonNameStr
, commonNameStr
, acceptedTaxon
);
306 for (String imageUrl
: taxonDataHolder
.getImages()){
307 TaxonDescription td
= acceptedTaxon
.getImageGallery(true);
308 DescriptionElementBase mediaHolder
;
309 if (td
.getElements().size() != 0){
310 mediaHolder
= td
.getElements().iterator().next();
312 mediaHolder
= TextData
.NewInstance(Feature
.IMAGE());
313 td
.addElement(mediaHolder
);
316 Media media
= getImageMedia(imageUrl
, READ_MEDIA_DATA
, false);
317 mediaHolder
.addMedia(media
);
318 } catch (MalformedURLException e
) {
319 logger
.warn("Can't add media: " + e
.getMessage());
320 state
.setUnsuccessfull();
325 for (String tdwg
: taxonDataHolder
.getDistributions()){
326 TaxonDescription td
= this.getTaxonDescription(acceptedTaxon
, state
.getConfig().getSourceReference() ,false, true);
327 NamedArea area
= TdwgArea
.getAreaByTdwgAbbreviation(tdwg
);
329 area
= TdwgArea
.getAreaByTdwgLabel(tdwg
);
332 Distribution distribution
= Distribution
.NewInstance(area
, PresenceTerm
.PRESENT());
333 td
.addElement(distribution
);
335 String message
= "TDWG area could not be recognized: " + tdwg
;
336 logger
.warn(message
);
337 state
.setUnsuccessfull();
342 handleFeatures(state
, taxonDataHolder
, acceptedTaxon
, nameUsedInSource
);
344 } catch (Exception e
) {
353 * @param taxonDataHolder
354 * @param acceptedTaxon
356 private void handleFeatures(TaxonExcelImportState state
, NormalExplicitRow taxonDataHolder
, Taxon acceptedTaxon
, TaxonNameBase nameUsedInSource
) {
358 for (UUID featureUuid
: taxonDataHolder
.getFeatures()){
359 Feature feature
= getFeature(state
, featureUuid
);
360 List
<String
> textList
= taxonDataHolder
.getFeatureTexts(featureUuid
);
361 List
<String
> languageList
= taxonDataHolder
.getFeatureLanguages(featureUuid
);
363 for (int i
= 0; i
< textList
.size(); i
++){
364 String featureText
= textList
.get(i
);
365 String featureLanguage
= languageList
== null ?
null :languageList
.get(i
);
366 Language language
= getFeatureLanguage(featureLanguage
, state
);
368 TaxonDescription td
= this.getTaxonDescription(acceptedTaxon
, state
.getConfig().getSourceReference() ,false, true);
369 TextData textData
= TextData
.NewInstance(feature
);
370 textData
.putText(language
, featureText
);
371 td
.addElement(textData
);
373 SourceDataHolder sourceDataHolder
= taxonDataHolder
.getFeatureTextReferences(featureUuid
, i
);
374 List
<Map
<SourceType
, String
>> sourceList
= sourceDataHolder
.getSources();
375 for (Map
<SourceType
, String
> sourceMap
: sourceList
){
377 DescriptionElementSource source
= DescriptionElementSource
.NewInstance();
379 Reference
<?
> ref
= ReferenceFactory
.newGeneric();
380 boolean refExists
= false; //in case none of the ref fields exists, the ref should not be added
381 for (SourceType type
: sourceMap
.keySet()){
382 String value
= sourceMap
.get(type
);
383 if (type
.equals(SourceType
.Author
)){
384 TeamOrPersonBase author
= getAuthorAccordingToConfig(value
, state
);
385 ref
.setAuthorTeam(author
);
386 }else if (type
.equals(SourceType
.Title
)) {
388 }else if (type
.equals(SourceType
.Year
)) {
389 ref
.setDatePublished(TimePeriod
.parseString(value
));
390 }else if (type
.equals(SourceType
.RefExtension
)) {
391 ExtensionType extensionType
= getExtensionType(state
, uuidRefExtension
, "RefExtension", "Reference Extension", "RefExt.");
392 Extension extension
= Extension
.NewInstance(ref
, value
, extensionType
);
397 ref
= getReferenceAccordingToConfig(ref
, state
);
398 source
.setCitation(ref
);
399 source
.setNameUsedInSource(nameUsedInSource
);
401 textData
.addSource(source
);
407 private Map
<String
, UUID
> referenceMapping
= new HashMap
<String
, UUID
>();
408 private Map
<UUID
, Reference
> referenceStore
= new HashMap
<UUID
, Reference
>();
410 private Reference
getReferenceAccordingToConfig(Reference value
, TaxonExcelImportState state
) {
411 Reference result
= null;
412 String titleCache
= value
.getTitleCache();
413 UUID referenceUuid
= referenceMapping
.get(titleCache
);
414 if (referenceUuid
!= null){
415 result
= referenceStore
.get(referenceUuid
);
419 referenceStore
.put(result
.getUuid(), result
);
421 if (referenceUuid
== null){
422 referenceMapping
.put(titleCache
, result
.getUuid());
428 private Map
<String
, UUID
> authorMapping
= new HashMap
<String
, UUID
>();
429 private Map
<UUID
, TeamOrPersonBase
> authorStore
= new HashMap
<UUID
, TeamOrPersonBase
>();
431 private TeamOrPersonBase
getAuthorAccordingToConfig(String value
, TaxonExcelImportState state
) {
432 TeamOrPersonBase result
= null;
433 UUID authorUuid
= authorMapping
.get(value
);
434 if (authorUuid
!= null){
435 result
= authorStore
.get(authorUuid
);
439 TeamOrPersonBase author
= Team
.NewInstance();
440 author
.setTitleCache(value
, true);
442 authorStore
.put(result
.getUuid(), result
);
444 if (authorUuid
== null){
445 authorMapping
.put(value
, result
.getUuid());
451 private Map
<String
, UUID
> languageMapping
= new HashMap
<String
, UUID
>();
453 private Language
getFeatureLanguage(String featureLanguage
, TaxonExcelImportState state
) {
454 if (StringUtils
.isBlank(featureLanguage
)){
457 UUID languageUuid
= languageMapping
.get(featureLanguage
);
458 if (languageUuid
== null){
459 Language result
= getTermService().getLanguageByIso(featureLanguage
);
460 languageUuid
= result
.getUuid();
461 languageMapping
.put(featureLanguage
, languageUuid
);
463 Language result
= getLanguage(state
, languageUuid
, null, null, null);
470 * @param taxonNameStr
471 * @param commonNameStr
474 private void handleCommonName(TaxonExcelImportState state
,
475 String taxonNameStr
, String commonNameStr
, Taxon acceptedTaxon
) {
476 Language language
= getTermService().getLanguageByIso(state
.getCurrentRow().getLanguage());
477 if (language
== null && CdmUtils
.isNotEmpty(state
.getCurrentRow().getLanguage()) ){
478 String error
="Language is null but shouldn't";
480 throw new IllegalArgumentException(error
);
482 CommonTaxonName commonTaxonName
= CommonTaxonName
.NewInstance(commonNameStr
, language
);
484 TaxonDescription taxonDescription
= getTaxonDescription(acceptedTaxon
, false, true);
485 taxonDescription
.addElement(commonTaxonName
);
486 logger
.info("Common name " + commonNameStr
+ " added to " + acceptedTaxon
.getTitleCache());
487 } catch (ClassCastException ex
) {
488 logger
.error(taxonNameStr
+ " is not a taxon instance.");
496 * @param taxonNameStr
501 private TaxonBase
createTaxon(TaxonExcelImportState state
, Rank rank
,
502 String taxonNameStr
, String authorStr
, String nameStatus
) {
503 // Create the taxon name object depending on the setting of the nomenclatural code
504 // in the configurator (botanical code, zoological code, etc.)
505 if (StringUtils
.isBlank(taxonNameStr
)){
508 NomenclaturalCode nc
= getConfigurator().getNomenclaturalCode();
510 TaxonBase taxonBase
= null;
512 String titleCache
= CdmUtils
.concat(" ", taxonNameStr
, authorStr
);
513 if (! synonymMarkers
.contains(nameStatus
) && state
.getConfig().isDoMatchTaxa()){
514 titleCache
= CdmUtils
.concat(" ", taxonNameStr
, authorStr
);
515 taxonBase
= getTaxonService().findBestMatchingTaxon(titleCache
);
517 taxonBase
= getTaxonService().findBestMatchingSynonym(titleCache
);
518 if (taxonBase
!= null){
519 logger
.info("Matching taxon/synonym found for " + titleCache
);
522 if (taxonBase
!= null){
523 logger
.info("Matching taxon/synonym found for " + titleCache
);
525 taxonBase
= createTaxon(state
, rank
, taxonNameStr
, authorStr
, nameStatus
, nc
);
536 * @param taxonNameStr
542 private TaxonBase
<?
> createTaxon(TaxonExcelImportState state
, Rank rank
, String taxonNameStr
,
543 String authorStr
, String nameStatus
, NomenclaturalCode nc
) {
544 TaxonBase
<?
> taxonBase
;
545 NonViralName
<?
> taxonNameBase
= null;
546 if (nc
== NomenclaturalCode
.ICVCN
){
547 logger
.warn("ICVCN not yet supported");
550 taxonNameBase
=(NonViralName
) nc
.getNewTaxonNameInstance(rank
);
551 //NonViralName nonViralName = (NonViralName)taxonNameBase;
552 NonViralNameParserImpl parser
= NonViralNameParserImpl
.NewInstance();
553 taxonNameBase
= parser
.parseFullName(taxonNameStr
, nc
, rank
);
555 taxonNameBase
.setNameCache(taxonNameStr
);
558 if (CdmUtils
.isNotEmpty(authorStr
)) {
560 parser
.parseAuthors(taxonNameBase
, authorStr
);
561 } catch (StringNotParsableException e
) {
562 taxonNameBase
.setAuthorshipCache(authorStr
);
568 Reference
<?
> sec
= state
.getConfig().getSourceReference();
570 nameStatus
= CdmUtils
.Nz(nameStatus
).trim().toLowerCase();
571 if (validMarkers
.contains(nameStatus
)){
572 taxonBase
= Taxon
.NewInstance(taxonNameBase
, sec
);
573 }else if (synonymMarkers
.contains(nameStatus
)){
574 taxonBase
= Synonym
.NewInstance(taxonNameBase
, sec
);
576 Taxon taxon
= Taxon
.NewInstance(taxonNameBase
, sec
);
577 taxon
.setTaxonStatusUnknown(true);
587 //TODO implementation must be improved when matching of taxon names with existing names is implemented
588 //=> the assumption that the only description is the description added by this import
590 private TaxonNameDescription
getNameDescription(TaxonNameBase
<?
,?
> name
) {
591 Set
<TaxonNameDescription
> descriptions
= name
.getDescriptions();
592 if (descriptions
.size()>1){
593 throw new IllegalStateException("Implementation does not yet support names with multiple descriptions");
594 }else if (descriptions
.size()==1){
595 return descriptions
.iterator().next();
597 return TaxonNameDescription
.NewInstance(name
);
601 private void makeParent(TaxonExcelImportState state
, Taxon parentTaxon
, Taxon childTaxon
, Reference citation
, String microCitation
){
602 Reference sec
= state
.getConfig().getSourceReference();
604 // Reference sec = parentTaxon.getSec();
605 Classification tree
= state
.getTree(sec
);
607 tree
= makeTree(state
, sec
);
609 if (sec
.equals(childTaxon
.getSec())){
610 boolean success
= (null != tree
.addParentChild(parentTaxon
, childTaxon
, citation
, microCitation
));
611 if (success
== false){
612 state
.setUnsuccessfull();
615 logger
.warn("No relationship added for child " + childTaxon
.getTitleCache());
622 * @see eu.etaxonomy.cdm.io.excel.common.ExcelTaxonOrSpecimenImportBase#createDataHolderRow()
625 protected NormalExplicitRow
createDataHolderRow() {
626 return new NormalExplicitRow();
632 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IoStateBase)
635 protected boolean doCheck(TaxonExcelImportState state
) {
636 logger
.warn("DoCheck not yet implemented for NormalExplicitImport");
641 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IoStateBase)
644 protected boolean isIgnore(TaxonExcelImportState state
) {