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
.common
.TdwgAreaProvider
;
29 import eu
.etaxonomy
.cdm
.io
.excel
.common
.ExcelRowBase
.SourceDataHolder
;
30 import eu
.etaxonomy
.cdm
.model
.agent
.Team
;
31 import eu
.etaxonomy
.cdm
.model
.agent
.TeamOrPersonBase
;
32 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
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
.OriginalSourceType
;
37 import eu
.etaxonomy
.cdm
.model
.description
.CommonTaxonName
;
38 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
39 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementSource
;
40 import eu
.etaxonomy
.cdm
.model
.description
.Distribution
;
41 import eu
.etaxonomy
.cdm
.model
.description
.Feature
;
42 import eu
.etaxonomy
.cdm
.model
.description
.PresenceTerm
;
43 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
44 import eu
.etaxonomy
.cdm
.model
.description
.TaxonNameDescription
;
45 import eu
.etaxonomy
.cdm
.model
.description
.TextData
;
46 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
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
;
62 import eu
.etaxonomy
.cdm
.strategy
.parser
.TimePeriodParser
;
65 * @author a.babadshanjan
70 public class NormalExplicitImport
extends TaxonExcelImporterBase
{
71 private static final Logger logger
= Logger
.getLogger(NormalExplicitImport
.class);
73 public static Set
<String
> validMarkers
= new HashSet
<String
>(Arrays
.asList(new String
[]{"", "valid", "accepted", "a", "v", "t"}));
74 public static Set
<String
> synonymMarkers
= new HashSet
<String
>(Arrays
.asList(new String
[]{"", "invalid", "synonym", "s", "i"}));
75 public static final UUID uuidRefExtension
= UUID
.fromString("a46533df-7a78-448f-9b80-36d087fbdf2a");
78 * @see eu.etaxonomy.cdm.io.excel.common.ExcelTaxonOrSpecimenImportBase#analyzeSingleValue(eu.etaxonomy.cdm.io.excel.common.ExcelTaxonOrSpecimenImportBase.KeyValue, eu.etaxonomy.cdm.io.excel.common.ExcelImportState)
81 protected void analyzeSingleValue(KeyValue keyValue
, TaxonExcelImportState state
) {
83 NormalExplicitRow normalExplicitRow
= state
.getCurrentRow();
84 String key
= keyValue
.key
;
85 String value
= keyValue
.value
;
86 Integer index
= keyValue
.index
;
87 if (key
.equalsIgnoreCase(ID_COLUMN
)) {
88 int ivalue
= floatString2IntValue(value
);
89 normalExplicitRow
.setId(ivalue
);
91 } else if(key
.equalsIgnoreCase(PARENT_ID_COLUMN
)) {
92 int ivalue
= floatString2IntValue(value
);
93 normalExplicitRow
.setParentId(ivalue
);
95 } else if(key
.equalsIgnoreCase(RANK_COLUMN
)) {
96 normalExplicitRow
.setRank(value
);
98 } else if(key
.equalsIgnoreCase(SCIENTIFIC_NAME_COLUMN
)) {
99 normalExplicitRow
.setScientificName(value
);
101 } else if(key
.equalsIgnoreCase(AUTHOR_COLUMN
)) {
102 normalExplicitRow
.setAuthor(value
);
104 } else if(key
.equalsIgnoreCase(REFERENCE_COLUMN
)) {
105 normalExplicitRow
.setReference(value
);
107 } else if(key
.equalsIgnoreCase(NAME_STATUS_COLUMN
)) {
108 normalExplicitRow
.setNameStatus(value
);
110 } else if(key
.equalsIgnoreCase(VERNACULAR_NAME_COLUMN
)) {
111 normalExplicitRow
.setCommonName(value
);
113 } else if(key
.equalsIgnoreCase(LANGUAGE_COLUMN
)) {
114 normalExplicitRow
.setLanguage(value
);
116 } else if(key
.equalsIgnoreCase(TDWG_COLUMN
)) {
117 //TODO replace still necessary?
118 value
= value
.replace(".0", "");
119 normalExplicitRow
.putDistribution(index
, value
);
121 } else if(key
.equalsIgnoreCase(PROTOLOGUE_COLUMN
)) {
122 normalExplicitRow
.putProtologue(index
, value
);
124 } else if(key
.equalsIgnoreCase(IMAGE_COLUMN
)) {
125 normalExplicitRow
.putImage(index
, value
);
128 if (analyzeFeatures(state
, keyValue
)){
131 String message
= "Unexpected column header " + key
;
132 fireWarningEvent(message
, state
, 10);
133 state
.setUnsuccessfull();
134 logger
.error(message
);
142 * Create base taxa and add all information attached to it's name.
145 protected void firstPass(TaxonExcelImportState state
) {
150 // System.out.println("FP:" + state.getCurrentLine());
152 NormalExplicitRow taxonDataHolder
= state
.getCurrentRow();
154 String rankStr
= taxonDataHolder
.getRank();
155 String taxonNameStr
= taxonDataHolder
.getScientificName();
156 String authorStr
= taxonDataHolder
.getAuthor();
157 String referenceStr
= taxonDataHolder
.getReference();
158 String nameStatus
= taxonDataHolder
.getNameStatus();
159 Integer id
= taxonDataHolder
.getId();
160 UUID cdmUuid
= taxonDataHolder
.getCdmUuid();
162 TaxonBase
<?
> taxonBase
= null;
163 if (cdmUuid
!= null){
164 taxonBase
= getTaxonService().find(cdmUuid
);
166 if (StringUtils
.isNotBlank(taxonNameStr
)) {
170 rank
= Rank
.getRankByNameOrIdInVoc(rankStr
);
171 } catch (UnknownCdmTypeException ex
) {
173 rank
= Rank
.getRankByEnglishName(rankStr
, state
.getConfig().getNomenclaturalCode(), false);
174 } catch (UnknownCdmTypeException e
) {
175 state
.setUnsuccessfull();
176 logger
.error(rankStr
+ " is not a valid rank.");
181 taxonBase
= createTaxon(state
, rank
, taxonNameStr
, authorStr
, referenceStr
, nameStatus
);
186 if (taxonBase
== null){
187 String message
= "Taxon could not be created. Record will not be handled";
188 fireWarningEvent(message
, "Record: " + state
.getCurrentLine(), 6);
189 logger
.warn(message
);
190 state
.setUnsuccessfull();
195 for (String protologue
: taxonDataHolder
.getProtologues()){
196 TextData textData
= TextData
.NewInstance(Feature
.PROTOLOGUE());
197 this.getNameDescription(taxonBase
.getName()).addElement(textData
);
200 uri
= new URI(protologue
);
201 textData
.addMedia(Media
.NewInstance(uri
, null, null, null));
202 } catch (URISyntaxException e
) {
203 String warning
= "URISyntaxException when trying to convert to URI: " + protologue
;
204 logger
.error(warning
);
205 state
.setUnsuccessfull();
209 state
.putTaxon(id
, taxonBase
);
210 getTaxonService().save(taxonBase
);
218 * Stores parent-child, synonym and common name relationships.
219 * Adds all taxon related descriptive information (this is not done in the first pass
220 * because the information may also be attached to a synonym).
223 protected void secondPass(TaxonExcelImportState state
) {
224 if (logger
.isDebugEnabled()){logger
.debug(state
.getCurrentLine());}
226 NormalExplicitRow taxonDataHolder
= state
.getCurrentRow();
227 String taxonNameStr
= taxonDataHolder
.getScientificName();
228 String nameStatus
= taxonDataHolder
.getNameStatus();
229 String commonNameStr
= taxonDataHolder
.getCommonName();
230 Integer parentId
= taxonDataHolder
.getParentId();
231 Integer childId
= taxonDataHolder
.getId();
232 UUID cdmUuid
= taxonDataHolder
.getCdmUuid();
234 TaxonNameBase
<?
,?
> nameUsedInSource
;
236 if (cdmUuid
!= null){
237 TaxonBase
<?
> taxonBase
= getTaxonService().find(cdmUuid
);
238 acceptedTaxon
= getAcceptedTaxon(taxonBase
);
239 nameUsedInSource
= taxonBase
.getName();
241 //TODO error handling for class cast
242 Taxon parentTaxon
= CdmBase
.deproxy(state
.getTaxonBase(parentId
), Taxon
.class);
243 if (StringUtils
.isNotBlank(taxonNameStr
)) {
244 TaxonBase
<?
> taxonBase
= state
.getTaxonBase(childId
);
245 nameUsedInSource
= taxonBase
.getName();
246 nameStatus
= CdmUtils
.Nz(nameStatus
).trim().toLowerCase();
247 if (validMarkers
.contains(nameStatus
)){
248 Taxon taxon
= CdmBase
.deproxy(taxonBase
, Taxon
.class);
249 acceptedTaxon
= taxon
;
250 // Add the parent relationship
251 if (state
.getCurrentRow().getParentId() != 0) {
252 if (parentTaxon
!= null) {
253 //Taxon taxon = (Taxon)state.getTaxonBase(childId);
255 Reference
<?
> sourceRef
= state
.getConfig().getSourceReference();
256 String microCitation
= null;
257 Taxon childTaxon
= taxon
;
258 makeParent(state
, parentTaxon
, childTaxon
, sourceRef
, microCitation
);
259 getTaxonService().saveOrUpdate(parentTaxon
);
261 String message
= "Taxonomic parent not found for " + taxonNameStr
;
262 logger
.warn(message
);
263 fireWarningEvent(message
, state
, 6);
264 state
.setUnsuccessfull();
267 //do nothing (parent == 0) no parent exists
269 }else if (synonymMarkers
.contains(nameStatus
)){
270 //add synonym relationship
271 acceptedTaxon
= parentTaxon
;
273 Synonym synonym
= CdmBase
.deproxy(taxonBase
,Synonym
.class);
274 if (acceptedTaxon
== null){
275 String message
= "Accepted/valid taxon could not be found. Please check referential integrity.";
276 fireWarningEvent(message
, state
, 8);
278 acceptedTaxon
.addSynonym(synonym
, SynonymRelationshipType
.SYNONYM_OF());
279 getTaxonService().saveOrUpdate(acceptedTaxon
);
281 } catch (Exception e
) {
282 String message
= "Unhandled exception (%s) occurred during synonym import/update";
283 message
= String
.format(message
, e
.getMessage());
284 fireWarningEvent(message
, state
, 10);
285 state
.setUnsuccessfull();
288 acceptedTaxon
= null;
289 String message
= "Unhandled name status (%s)";
290 message
= String
.format(message
, nameStatus
);
291 fireWarningEvent(message
, state
, 8);
293 }else{//taxonNameStr is empty
294 //vernacular name case
295 acceptedTaxon
= parentTaxon
;
296 nameUsedInSource
= null;
300 if (acceptedTaxon
== null && (StringUtils
.isNotBlank(commonNameStr
) ||taxonDataHolder
.getFeatures().size() > 0 )){
301 String message
= "Accepted taxon could not be found. Can't add additional data (common names, descriptive data, ...) to taxon";
302 fireWarningEvent(message
, state
, 6);
305 if (StringUtils
.isNotBlank(commonNameStr
)){ // add common name to taxon
306 handleCommonName(state
, taxonNameStr
, commonNameStr
, acceptedTaxon
);
311 for (String imageUrl
: taxonDataHolder
.getImages()){
312 TaxonDescription td
= acceptedTaxon
.getImageGallery(true);
313 DescriptionElementBase mediaHolder
;
314 if (td
.getElements().size() != 0){
315 mediaHolder
= td
.getElements().iterator().next();
317 mediaHolder
= TextData
.NewInstance(Feature
.IMAGE());
318 td
.addElement(mediaHolder
);
321 Media media
= getImageMedia(imageUrl
, READ_MEDIA_DATA
);
322 mediaHolder
.addMedia(media
);
323 } catch (MalformedURLException e
) {
324 logger
.warn("Can't add media: " + e
.getMessage());
325 state
.setUnsuccessfull();
330 for (String tdwg
: taxonDataHolder
.getDistributions()){
331 TaxonDescription td
= this.getTaxonDescription(acceptedTaxon
, state
.getConfig().getSourceReference() ,false, true);
332 NamedArea area
= TdwgAreaProvider
.getAreaByTdwgAbbreviation(tdwg
);
334 area
= TdwgAreaProvider
.getAreaByTdwgLabel(tdwg
);
337 Distribution distribution
= Distribution
.NewInstance(area
, PresenceTerm
.PRESENT());
338 td
.addElement(distribution
);
340 String message
= "TDWG area could not be recognized: " + tdwg
;
341 logger
.warn(message
);
342 state
.setUnsuccessfull();
347 handleFeatures(state
, taxonDataHolder
, acceptedTaxon
, nameUsedInSource
);
349 } catch (Exception e
) {
358 * @param taxonDataHolder
359 * @param acceptedTaxon
361 private void handleFeatures(TaxonExcelImportState state
, NormalExplicitRow taxonDataHolder
, Taxon acceptedTaxon
, TaxonNameBase nameUsedInSource
) {
363 for (UUID featureUuid
: taxonDataHolder
.getFeatures()){
364 Feature feature
= getFeature(state
, featureUuid
);
365 List
<String
> textList
= taxonDataHolder
.getFeatureTexts(featureUuid
);
366 List
<String
> languageList
= taxonDataHolder
.getFeatureLanguages(featureUuid
);
368 for (int i
= 0; i
< textList
.size(); i
++){
369 String featureText
= textList
.get(i
);
370 String featureLanguage
= languageList
== null ?
null :languageList
.get(i
);
371 Language language
= getFeatureLanguage(featureLanguage
, state
);
373 TaxonDescription td
= this.getTaxonDescription(acceptedTaxon
, state
.getConfig().getSourceReference() ,false, true);
374 TextData textData
= TextData
.NewInstance(feature
);
375 textData
.putText(language
, featureText
);
376 td
.addElement(textData
);
378 SourceDataHolder sourceDataHolder
= taxonDataHolder
.getFeatureTextReferences(featureUuid
, i
);
379 List
<Map
<SourceType
, String
>> sourceList
= sourceDataHolder
.getSources();
380 for (Map
<SourceType
, String
> sourceMap
: sourceList
){
383 Reference
<?
> ref
= ReferenceFactory
.newGeneric();
384 boolean refExists
= false; //in case none of the ref fields exists, the ref should not be added
385 for (SourceType type
: sourceMap
.keySet()){
386 String value
= sourceMap
.get(type
);
387 if (type
.equals(SourceType
.Author
)){
388 TeamOrPersonBase
<?
> author
= getAuthorAccordingToConfig(value
, state
);
389 ref
.setAuthorTeam(author
);
390 }else if (type
.equals(SourceType
.Title
)) {
392 }else if (type
.equals(SourceType
.Year
)) {
393 ref
.setDatePublished(TimePeriodParser
.parseString(value
));
394 }else if (type
.equals(SourceType
.RefExtension
)) {
395 ExtensionType extensionType
= getExtensionType(state
, uuidRefExtension
, "RefExtension", "Reference Extension", "RefExt.");
396 Extension extension
= Extension
.NewInstance(ref
, value
, extensionType
);
400 DescriptionElementSource source
= DescriptionElementSource
.NewInstance(OriginalSourceType
.PrimaryTaxonomicSource
);
402 ref
= getReferenceAccordingToConfig(ref
, state
);
403 source
.setCitation(ref
);
404 source
.setNameUsedInSource(nameUsedInSource
);
406 textData
.addSource(source
);
412 private Map
<String
, UUID
> referenceMapping
= new HashMap
<String
, UUID
>();
413 private Map
<UUID
, Reference
> referenceStore
= new HashMap
<UUID
, Reference
>();
415 private Reference
getReferenceAccordingToConfig(Reference value
, TaxonExcelImportState state
) {
416 Reference result
= null;
417 String titleCache
= value
.getTitleCache();
418 UUID referenceUuid
= referenceMapping
.get(titleCache
);
419 if (referenceUuid
!= null){
420 result
= referenceStore
.get(referenceUuid
);
424 referenceStore
.put(result
.getUuid(), result
);
426 if (referenceUuid
== null){
427 referenceMapping
.put(titleCache
, result
.getUuid());
433 private Map
<String
, UUID
> authorMapping
= new HashMap
<String
, UUID
>();
434 private Map
<UUID
, TeamOrPersonBase
> authorStore
= new HashMap
<UUID
, TeamOrPersonBase
>();
436 private TeamOrPersonBase
<?
> getAuthorAccordingToConfig(String value
, TaxonExcelImportState state
) {
437 TeamOrPersonBase
<?
> result
= null;
438 UUID authorUuid
= authorMapping
.get(value
);
439 if (authorUuid
!= null){
440 result
= authorStore
.get(authorUuid
);
444 TeamOrPersonBase
<?
> author
= Team
.NewInstance();
445 author
.setTitleCache(value
, true);
447 authorStore
.put(result
.getUuid(), result
);
449 if (authorUuid
== null){
450 authorMapping
.put(value
, result
.getUuid());
456 private Map
<String
, UUID
> languageMapping
= new HashMap
<String
, UUID
>();
458 private Language
getFeatureLanguage(String featureLanguage
, TaxonExcelImportState state
) {
459 if (StringUtils
.isBlank(featureLanguage
)){
462 UUID languageUuid
= languageMapping
.get(featureLanguage
);
463 if (languageUuid
== null){
464 Language result
= getTermService().getLanguageByIso(featureLanguage
);
465 languageUuid
= result
.getUuid();
466 languageMapping
.put(featureLanguage
, languageUuid
);
468 Language result
= getLanguage(state
, languageUuid
, null, null, null);
475 * @param taxonNameStr
476 * @param commonNameStr
479 private void handleCommonName(TaxonExcelImportState state
,
480 String taxonNameStr
, String commonNameStr
, Taxon acceptedTaxon
) {
481 Language language
= getTermService().getLanguageByIso(state
.getCurrentRow().getLanguage());
482 if (language
== null && CdmUtils
.isNotEmpty(state
.getCurrentRow().getLanguage()) ){
483 String error
="Language is null but shouldn't";
485 throw new IllegalArgumentException(error
);
487 CommonTaxonName commonTaxonName
= CommonTaxonName
.NewInstance(commonNameStr
, language
);
489 TaxonDescription taxonDescription
= getTaxonDescription(acceptedTaxon
, false, true);
490 taxonDescription
.addElement(commonTaxonName
);
491 logger
.info("Common name " + commonNameStr
+ " added to " + acceptedTaxon
.getTitleCache());
492 } catch (ClassCastException ex
) {
493 logger
.error(taxonNameStr
+ " is not a taxon instance.");
501 * @param taxonNameStr
507 private TaxonBase
createTaxon(TaxonExcelImportState state
, Rank rank
,
508 String taxonNameStr
, String authorStr
, String reference
, String nameStatus
) {
509 // Create the taxon name object depending on the setting of the nomenclatural code
510 // in the configurator (botanical code, zoological code, etc.)
511 if (StringUtils
.isBlank(taxonNameStr
)){
514 NomenclaturalCode nc
= getConfigurator().getNomenclaturalCode();
518 String titleCache
= CdmUtils
.concat(" ", taxonNameStr
, authorStr
);
519 if (! synonymMarkers
.contains(nameStatus
) && state
.getConfig().isReuseExistingTaxaWhenPossible()){
520 titleCache
= CdmUtils
.concat(" ", taxonNameStr
, authorStr
);
521 taxonBase
= getTaxonService().findBestMatchingTaxon(titleCache
);
523 taxonBase
= getTaxonService().findBestMatchingSynonym(titleCache
);
524 if (taxonBase
!= null){
525 logger
.info("Matching taxon/synonym found for " + titleCache
);
528 if (taxonBase
!= null){
529 logger
.info("Matching taxon/synonym found for " + titleCache
);
531 taxonBase
= createTaxon(state
, rank
, taxonNameStr
, authorStr
, reference
, nameStatus
, nc
);
542 * @param taxonNameStr
549 private TaxonBase
<?
> createTaxon(TaxonExcelImportState state
, Rank rank
, String taxonNameStr
,
550 String authorStr
, String reference
, String nameStatus
, NomenclaturalCode nc
) {
551 TaxonBase
<?
> taxonBase
;
552 NonViralName
<?
> taxonNameBase
= null;
553 if (nc
== NomenclaturalCode
.ICVCN
){
554 logger
.warn("ICVCN not yet supported");
557 taxonNameBase
=(NonViralName
<?
>) nc
.getNewTaxonNameInstance(rank
);
558 //NonViralName nonViralName = (NonViralName)taxonNameBase;
559 NonViralNameParserImpl parser
= NonViralNameParserImpl
.NewInstance();
560 taxonNameBase
= parser
.parseFullName(taxonNameStr
, nc
, rank
);
562 if (! taxonNameBase
.getNameCache().equals(taxonNameStr
)){
563 taxonNameBase
.setNameCache(taxonNameStr
, true);
567 if (StringUtils
.isNotBlank(authorStr
)) {
569 parser
.parseAuthors(taxonNameBase
, authorStr
);
570 } catch (StringNotParsableException e
) {
571 taxonNameBase
.setAuthorshipCache(authorStr
);
577 Reference
<?
> sec
= state
.getConfig().getSourceReference();
579 nameStatus
= CdmUtils
.Nz(nameStatus
).trim().toLowerCase();
580 if (validMarkers
.contains(nameStatus
)){
581 taxonBase
= Taxon
.NewInstance(taxonNameBase
, sec
);
582 }else if (synonymMarkers
.contains(nameStatus
)){
583 taxonBase
= Synonym
.NewInstance(taxonNameBase
, sec
);
585 Taxon taxon
= Taxon
.NewInstance(taxonNameBase
, sec
);
586 taxon
.setTaxonStatusUnknown(true);
596 //TODO implementation must be improved when matching of taxon names with existing names is implemented
597 //=> the assumption that the only description is the description added by this import
599 private TaxonNameDescription
getNameDescription(TaxonNameBase
<?
,?
> name
) {
600 Set
<TaxonNameDescription
> descriptions
= name
.getDescriptions();
601 if (descriptions
.size()>1){
602 throw new IllegalStateException("Implementation does not yet support names with multiple descriptions");
603 }else if (descriptions
.size()==1){
604 return descriptions
.iterator().next();
606 return TaxonNameDescription
.NewInstance(name
);
610 private void makeParent(TaxonExcelImportState state
, Taxon parentTaxon
, Taxon childTaxon
, Reference
<?
> citation
, String microCitation
){
611 Reference
<?
> sec
= state
.getConfig().getSourceReference();
613 // Reference sec = parentTaxon.getSec();
614 Classification tree
= state
.getTree(sec
);
616 tree
= makeTree(state
, sec
);
618 if (sec
.equals(childTaxon
.getSec())){
619 boolean success
= (null != tree
.addParentChild(parentTaxon
, childTaxon
, citation
, microCitation
));
620 if (success
== false){
621 state
.setUnsuccessfull();
624 logger
.warn("No relationship added for child " + childTaxon
.getTitleCache());
631 * @see eu.etaxonomy.cdm.io.excel.common.ExcelTaxonOrSpecimenImportBase#createDataHolderRow()
634 protected NormalExplicitRow
createDataHolderRow() {
635 return new NormalExplicitRow();
641 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IoStateBase)
644 protected boolean doCheck(TaxonExcelImportState state
) {
645 logger
.warn("DoCheck not yet implemented for NormalExplicitImport");
650 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IoStateBase)
653 protected boolean isIgnore(TaxonExcelImportState state
) {