Project

General

Profile

Download (26.7 KB) Statistics
| Branch: | Tag: | Revision:
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.excel.taxa;
11

    
12
import java.net.MalformedURLException;
13
import java.net.URI;
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;
19
import java.util.Map;
20
import java.util.Set;
21
import java.util.UUID;
22

    
23
import org.apache.commons.lang.StringUtils;
24
import org.apache.log4j.Logger;
25
import org.springframework.stereotype.Component;
26

    
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.PresenceAbsenceTerm;
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.NomenclaturalStatusType;
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.INomenclaturalReference;
54
import eu.etaxonomy.cdm.model.reference.Reference;
55
import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
56
import eu.etaxonomy.cdm.model.taxon.Classification;
57
import eu.etaxonomy.cdm.model.taxon.Synonym;
58
import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
59
import eu.etaxonomy.cdm.model.taxon.Taxon;
60
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
61
import eu.etaxonomy.cdm.persistence.dto.MergeResult;
62
import eu.etaxonomy.cdm.strategy.exceptions.StringNotParsableException;
63
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
64
import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
65
import eu.etaxonomy.cdm.strategy.parser.TimePeriodParser;
66

    
67
/**
68
 * @author a.babadshanjan
69
 * @created 08.01.2009
70
 */
71

    
72
@Component
73
public class NormalExplicitImport extends TaxonExcelImporterBase {
74
    private static final long serialVersionUID = 3642423349766191160L;
75

    
76
    private static final Logger logger = Logger.getLogger(NormalExplicitImport.class);
77

    
78
	public static Set<String> validMarkers = new HashSet<String>(Arrays.asList(new String[]{"", "valid", "accepted", "a", "v", "t", "!"}));
79
	public static Set<String> synonymMarkers = new HashSet<String>(Arrays.asList(new String[]{"**","invalid", "synonym", "s", "i"}));
80
	public static Set<String> nameStatusMarkers = new HashSet<String>(Arrays.asList(new String[]{"illegitimate", "nom. rej.", "nom. cons."}));
81
	public static final UUID uuidRefExtension = UUID.fromString("a46533df-7a78-448f-9b80-36d087fbdf2a");
82

    
83
    private static final Object NOM_ILLEG = "illegitimate";
84
    private static final Object NOM_REJ = "nom. rej.";
85
    private static final Object NOM_CONS = "nom. cons.";
86

    
87

    
88
	/* (non-Javadoc)
89
	 * @see eu.etaxonomy.cdm.io.excel.common.ExcelTaxonOrSpecimenImportBase#analyzeSingleValue(eu.etaxonomy.cdm.io.excel.common.ExcelTaxonOrSpecimenImportBase.KeyValue, eu.etaxonomy.cdm.io.excel.common.ExcelImportState)
90
	 */
91
	@Override
92
	protected void analyzeSingleValue(KeyValue keyValue, TaxonExcelImportState state) {
93

    
94
		NormalExplicitRow normalExplicitRow = state.getCurrentRow();
95
		String key = keyValue.key;
96
		String value = keyValue.value;
97
		Integer index = keyValue.index;
98
		if (((NormalExplicitImportConfigurator)state.getConfig()).getParentUUID() != null){
99
            normalExplicitRow.setParentId(0);
100
		}
101

    
102
		key = key.replace(" ","");
103
		if (key.equalsIgnoreCase(ID_COLUMN)) {
104
			int ivalue = floatString2IntValue(value);
105
			normalExplicitRow.setId(ivalue);
106

    
107
		} else if(key.equalsIgnoreCase(PARENT_ID_COLUMN) ) {
108
			int ivalue = floatString2IntValue(value);
109
			normalExplicitRow.setParentId(ivalue);
110

    
111
		} else if(key.equalsIgnoreCase(RANK_COLUMN)) {
112
			normalExplicitRow.setRank(value);
113

    
114
		} else if(key.trim().equalsIgnoreCase(SCIENTIFIC_NAME_COLUMN)) {
115
			normalExplicitRow.setScientificName(value);
116

    
117
		} else if(key.equalsIgnoreCase(AUTHOR_COLUMN)) {
118
			normalExplicitRow.setAuthor(value);
119

    
120
		} else if(key.equalsIgnoreCase(REFERENCE_COLUMN)) {
121
			normalExplicitRow.setReference(value);
122

    
123
		} else if(key.equalsIgnoreCase(NAME_STATUS_COLUMN) ) {
124
			normalExplicitRow.setNameStatus(value);
125

    
126
		} else if(key.equalsIgnoreCase(VERNACULAR_NAME_COLUMN)) {
127
			normalExplicitRow.setCommonName(value);
128

    
129
		} else if(key.equalsIgnoreCase(LANGUAGE_COLUMN)) {
130
			normalExplicitRow.setLanguage(value);
131

    
132
		} else if(key.equalsIgnoreCase(TDWG_COLUMN)) {
133
			//TODO replace still necessary?
134
			value = value.replace(".0", "");
135
			normalExplicitRow.putDistribution(index, value);
136

    
137
		} else if(key.equalsIgnoreCase(PROTOLOGUE_COLUMN)) {
138
			normalExplicitRow.putProtologue(index, value);
139

    
140
		} else if(key.equalsIgnoreCase(IMAGE_COLUMN)) {
141
			normalExplicitRow.putImage(index, value);
142

    
143
		} else if(key.equalsIgnoreCase(DATE_COLUMN) || key.equalsIgnoreCase(YEAR_COLUMN)) {
144
            normalExplicitRow.setDate(value);
145

    
146
        } else if(key.equalsIgnoreCase(FAMILY_COLUMN)) {
147
            normalExplicitRow.setFamily(value);
148
        }else if(key.equalsIgnoreCase("!")) {
149
            //! = Legitimate, * = Illegitimate, ** = Invalid, *** = nom. rej., !! = nom. cons.
150
            if (value.equals("!")){
151
                normalExplicitRow.setNameStatus("accepted");
152
            } else if (value.equals("*")){
153
                normalExplicitRow.setNameStatus("illegitimate");
154
            } else if (value.equals("**")){
155
                normalExplicitRow.setNameStatus("invalid");
156
            } else if (value.equals("***")){
157
                normalExplicitRow.setNameStatus("nom. rej.");
158
            } else if (value.equals("!!")){
159
                normalExplicitRow.setNameStatus("nom. cons.");
160
            } else{
161
                normalExplicitRow.setNameStatus("accepted");
162
            }
163
        }else {
164
			if (analyzeFeatures(state, keyValue)){
165
				//ok
166
			}else{
167
				String message = "Unexpected column header " + key;
168
				fireWarningEvent(message, state, 10);
169
				state.setUnsuccessfull();
170
				logger.error(message);
171
			}
172
		}
173
		return;
174
	}
175

    
176

    
177
	/**
178
	 *  Create base taxa and add all information attached to it's name.
179
	 */
180
	@Override
181
    protected void firstPass(TaxonExcelImportState state) {
182

    
183
//		if (1==1){
184
//			return;
185
//		}
186
//		System.out.println("FP:" + state.getCurrentLine());
187
		Rank rank = null;
188
		NormalExplicitRow taxonDataHolder = state.getCurrentRow();
189

    
190
		String rankStr = taxonDataHolder.getRank();
191
		String taxonNameStr = taxonDataHolder.getScientificName();
192
		String authorStr = taxonDataHolder.getAuthor();
193
		String referenceStr = taxonDataHolder.getReference();
194
		String nameStatus = taxonDataHolder.getNameStatus();
195
		String familyNameStr = taxonDataHolder.getFamily();
196
		String dateStr = taxonDataHolder.getDate();
197
		Integer id = taxonDataHolder.getId();
198
		UUID cdmUuid = taxonDataHolder.getCdmUuid();
199

    
200
		TaxonBase<?> taxonBase = null;
201
		if (cdmUuid != null){
202
			taxonBase = getTaxonService().find(cdmUuid);
203
		}else{
204
			if (StringUtils.isNotBlank(taxonNameStr)) {
205

    
206
				// Rank
207
				try {
208
				    if (!StringUtils.isBlank(rankStr)) {
209
                        rank = Rank.getRankByNameOrIdInVoc(rankStr);
210
                        }
211
				} catch (UnknownCdmTypeException ex) {
212
					try {
213
						rank = Rank.getRankByEnglishName(rankStr, state.getConfig().getNomenclaturalCode(), false);
214
					} catch (UnknownCdmTypeException e) {
215
						//state.setUnsuccessfull();
216
						logger.error(rankStr + " is not a valid rank.");
217
					}
218
				}
219

    
220
	            //taxon
221
				taxonBase = createTaxon(state, rank, taxonNameStr, authorStr, referenceStr, dateStr, nameStatus);
222
			}else{
223
				return;
224
			}
225
		}
226
		if (taxonBase == null){
227
			String message = "Taxon is already in DB. Record will not be handled";
228
			fireWarningEvent(message, "Record: " + state.getCurrentLine(), 6);
229
			logger.warn(message);
230
			//state.setUnsuccessfull();
231
			return;
232
		}
233

    
234
		//protologue
235
		for (String protologue : taxonDataHolder.getProtologues()){
236
			TextData textData = TextData.NewInstance(Feature.PROTOLOGUE());
237
			this.getNameDescription(taxonBase.getName()).addElement(textData);
238
			URI uri;
239
			try {
240
				uri = new URI(protologue);
241
				textData.addMedia(Media.NewInstance(uri, null, null, null));
242
			} catch (URISyntaxException e) {
243
				String warning = "URISyntaxException when trying to convert to URI: " + protologue;
244
				logger.error(warning);
245
				state.setUnsuccessfull();
246
			}
247
		}
248

    
249
		state.putTaxon(id, taxonBase);
250
		getTaxonService().save(taxonBase);
251

    
252
		return;
253
    }
254

    
255

    
256

    
257
	/**
258
	 *  Stores parent-child, synonym and common name relationships.
259
	 *  Adds all taxon related descriptive information (this is not done in the first pass
260
	 *  because the information may also be attached to a synonym).
261
	 */
262
	@Override
263
    protected void secondPass(TaxonExcelImportState state) {
264
		if (logger.isDebugEnabled()){logger.debug(state.getCurrentLine());}
265
		try {
266
			NormalExplicitRow taxonDataHolder = state.getCurrentRow();
267
			String taxonNameStr = taxonDataHolder.getScientificName();
268
			String nameStatus = taxonDataHolder.getNameStatus();
269
			String commonNameStr = taxonDataHolder.getCommonName();
270
			Integer parentId = taxonDataHolder.getParentId();
271
			Integer childId = taxonDataHolder.getId();
272
			UUID cdmUuid = taxonDataHolder.getCdmUuid();
273
			Taxon acceptedTaxon = null;
274
			TaxonNameBase<?,?> nameUsedInSource = null;
275
			TaxonBase<?> taxonBase = null;
276

    
277
			if (cdmUuid != null){
278
				taxonBase = getTaxonService().find(cdmUuid);
279
				acceptedTaxon = getAcceptedTaxon(taxonBase);
280
				nameUsedInSource = taxonBase.getName();
281
			}else{
282
			    //TODO error handling for class cast
283
			    Taxon parentTaxon = null;
284
			    if (parentId == 0 && state.getParent() == null){
285
			        parentTaxon =(Taxon) getTaxonService().load(((NormalExplicitImportConfigurator)state.getConfig()).getParentUUID());
286
			        state.setParent(parentTaxon);
287
			    }else if (parentId != 0){
288
			       parentTaxon = CdmBase.deproxy(state.getTaxonBase(parentId), Taxon.class);
289
			    } else if (state.getParent() != null){
290
			        parentTaxon = state.getParent();
291
			    }
292
				if (StringUtils.isNotBlank(taxonNameStr)) {
293
					taxonBase = state.getTaxonBase(childId);
294
					if (taxonBase != null){
295

    
296
					nameUsedInSource = taxonBase.getName();
297
					nameStatus = CdmUtils.Nz(nameStatus).trim().toLowerCase();
298
					if (validMarkers.contains(nameStatus)){
299
						Taxon taxon = CdmBase.deproxy(taxonBase, Taxon.class);
300
						acceptedTaxon = taxon;
301
						// Add the parent relationship
302
						//if (state.getCurrentRow().getParentId() != 0) {
303
						MergeResult result = null;
304
							if (parentTaxon != null) {
305
								//Taxon taxon = (Taxon)state.getTaxonBase(childId);
306

    
307
								Reference sourceRef = state.getConfig().getSourceReference();
308
								String microCitation = null;
309
								Taxon childTaxon = taxon;
310
								makeParent(state, parentTaxon, childTaxon, sourceRef, microCitation);
311
								getTaxonService().saveOrUpdate(parentTaxon);
312
								state.putTaxon(parentId, parentTaxon);
313
							} else {
314
								String message = "Taxonomic parent not found for " + taxonNameStr;
315
								logger.warn(message);
316
								fireWarningEvent(message, state, 6);
317
								//state.setUnsuccessfull();
318
							}
319
//						}else{
320
//							//do nothing (parent == 0) no parent exists
321
//						}
322
					}else if (synonymMarkers.contains(nameStatus)){
323
						//add synonym relationship
324
						acceptedTaxon = parentTaxon;
325
						try {
326
							Synonym synonym = CdmBase.deproxy(taxonBase,Synonym.class);
327
							if (acceptedTaxon == null){
328
								String message = "Accepted/valid taxon could not be found. Please check referential integrity.";
329
								fireWarningEvent(message, state, 8);
330
							}else{
331
							    if (parentId != 0){
332
							        //if no relation was defined in file skip relationship creation
333
							        acceptedTaxon.addSynonym(synonym, SynonymRelationshipType.SYNONYM_OF());
334
							        getTaxonService().saveOrUpdate(acceptedTaxon);
335
							    }
336
							}
337
						} catch (Exception e) {
338
							String message = "Unhandled exception (%s) occurred during synonym import/update";
339
							message = String.format(message, e.getMessage());
340
							fireWarningEvent(message, state, 10);
341
							state.setUnsuccessfull();
342
						}
343
					}
344
					}else{
345
						acceptedTaxon = null;
346
						String message = "Unhandled name status (%s)";
347
						message = String.format(message, nameStatus);
348
						fireWarningEvent(message, state, 8);
349
					}
350
				}else{//taxonNameStr is empty
351
					//vernacular name case
352
					acceptedTaxon = parentTaxon;
353
					nameUsedInSource = null;
354
				}
355
			}
356

    
357
			if (acceptedTaxon == null && (StringUtils.isNotBlank(commonNameStr) ||taxonDataHolder.getFeatures().size() > 0 )){
358
				String message = "Accepted taxon could not be found. Can't add additional data (common names, descriptive data, ...) to taxon";
359
				fireWarningEvent(message, state, 6);
360
			}else{
361
				//common names
362
				if (StringUtils.isNotBlank(commonNameStr)){			// add common name to taxon
363
					handleCommonName(state, taxonNameStr, commonNameStr, acceptedTaxon);
364
				}
365

    
366

    
367
				//media
368
				for (String imageUrl : taxonDataHolder.getImages()){
369
					TaxonDescription td = acceptedTaxon.getImageGallery(true);
370
					DescriptionElementBase mediaHolder;
371
					if (td.getElements().size() != 0){
372
						mediaHolder = td.getElements().iterator().next();
373
					}else{
374
						mediaHolder = TextData.NewInstance(Feature.IMAGE());
375
						td.addElement(mediaHolder);
376
					}
377
					try {
378
						Media media = getImageMedia(imageUrl, READ_MEDIA_DATA);
379
						mediaHolder.addMedia(media);
380
					} catch (MalformedURLException e) {
381
						logger.warn("Can't add media: " + e.getMessage());
382
						state.setUnsuccessfull();
383
					}
384
				}
385

    
386
				//tdwg label
387
				for (String tdwg : taxonDataHolder.getDistributions()){
388
					TaxonDescription td = this.getTaxonDescription(acceptedTaxon, state.getConfig().getSourceReference() ,false, true);
389
					NamedArea area = TdwgAreaProvider.getAreaByTdwgAbbreviation(tdwg);
390
					if (area == null){
391
						area = TdwgAreaProvider.getAreaByTdwgLabel(tdwg);
392
					}
393
					if (area != null){
394
						Distribution distribution = Distribution.NewInstance(area, PresenceAbsenceTerm.PRESENT());
395
						td.addElement(distribution);
396
					}else{
397
						String message = "TDWG area could not be recognized: " + tdwg;
398
						logger.warn(message);
399
						state.setUnsuccessfull();
400
					}
401
				}
402

    
403
				//features
404
				handleFeatures(state, taxonDataHolder, acceptedTaxon, nameUsedInSource);
405
			}
406
		} catch (Exception e) {
407
			e.printStackTrace();
408
		}
409
		return;
410
	}
411

    
412

    
413
	/**
414
	 * @param state
415
	 * @param taxonDataHolder
416
	 * @param acceptedTaxon
417
	 */
418
	private void handleFeatures(TaxonExcelImportState state, NormalExplicitRow taxonDataHolder, Taxon acceptedTaxon, TaxonNameBase nameUsedInSource) {
419
		//feature
420
		for (UUID featureUuid : taxonDataHolder.getFeatures()){
421
			Feature feature = getFeature(state, featureUuid);
422
			List<String> textList = taxonDataHolder.getFeatureTexts(featureUuid);
423
			List<String> languageList = taxonDataHolder.getFeatureLanguages(featureUuid);
424

    
425
			for (int i = 0; i < textList.size(); i++){
426
				String featureText = textList.get(i);
427
				String featureLanguage = languageList == null ? null :languageList.get(i);
428
				Language language = getFeatureLanguage(featureLanguage, state);
429
				//TODO
430
				TaxonDescription td = this.getTaxonDescription(acceptedTaxon, state.getConfig().getSourceReference() ,false, true);
431
				TextData textData = TextData.NewInstance(feature);
432
				textData.putText(language, featureText);
433
				td.addElement(textData);
434

    
435
				SourceDataHolder sourceDataHolder = taxonDataHolder.getFeatureTextReferences(featureUuid, i);
436
				List<Map<SourceType, String>> sourceList = sourceDataHolder.getSources();
437
				for (Map<SourceType, String> sourceMap : sourceList){
438

    
439
					//ref
440
					Reference ref = ReferenceFactory.newGeneric();
441
					boolean refExists = false; //in case none of the ref fields exists, the ref should not be added
442
					for (SourceType type : sourceMap.keySet()){
443
						String value = sourceMap.get(type);
444
						if (type.equals(SourceType.Author)){
445
							TeamOrPersonBase<?> author = getAuthorAccordingToConfig(value, state);
446
							ref.setAuthorship(author);
447
						}else if (type.equals(SourceType.Title)) {
448
							ref.setTitle(value);
449
						}else if (type.equals(SourceType.Year)) {
450
							ref.setDatePublished(TimePeriodParser.parseString(value));
451
						}else if (type.equals(SourceType.RefExtension)) {
452
							ExtensionType extensionType = getExtensionType(state, uuidRefExtension, "RefExtension", "Reference Extension", "RefExt.");
453
							Extension extension = Extension.NewInstance(ref, value, extensionType);
454
						}
455
						refExists = true;
456
					}
457
					DescriptionElementSource source = DescriptionElementSource.NewInstance(OriginalSourceType.PrimaryTaxonomicSource);
458
					if (refExists){
459
						ref = getReferenceAccordingToConfig(ref, state);
460
						source.setCitation(ref);
461
						source.setNameUsedInSource(nameUsedInSource);
462
					}
463
					textData.addSource(source);
464
				}
465
			}
466
		}
467
	}
468

    
469
	private final Map<String, UUID> referenceMapping = new HashMap<String, UUID>();
470
	private final Map<UUID, Reference> referenceStore = new HashMap<UUID, Reference>();
471

    
472
	private Reference getReferenceAccordingToConfig(Reference value, TaxonExcelImportState state) {
473
		Reference result = null;
474
		String titleCache = value.getTitleCache();
475
		UUID referenceUuid = referenceMapping.get(titleCache);
476
		if (referenceUuid != null){
477
			result = referenceStore.get(referenceUuid);
478
		}
479
		if (result == null){
480
			result = value;
481
			referenceStore.put(result.getUuid(), result);
482
		}
483
		if (referenceUuid == null){
484
			referenceMapping.put(titleCache, result.getUuid());
485
		}
486
		return result;
487
	}
488

    
489

    
490
	private final Map<String, UUID> authorMapping = new HashMap<String, UUID>();
491
	private final Map<UUID, TeamOrPersonBase> authorStore = new HashMap<UUID, TeamOrPersonBase>();
492

    
493
	private TeamOrPersonBase<?> getAuthorAccordingToConfig(String value, TaxonExcelImportState state) {
494
		TeamOrPersonBase<?> result = null;
495
		UUID authorUuid = authorMapping.get(value);
496
		if (authorUuid != null){
497
			result = authorStore.get(authorUuid);
498
		}
499
		if (result == null){
500
			//TODO parsing
501
			TeamOrPersonBase<?> author = Team.NewInstance();
502
			author.setTitleCache(value, true);
503
			result = author;
504
			authorStore.put(result.getUuid(), result);
505
		}
506
		if (authorUuid == null){
507
			authorMapping.put(value, result.getUuid());
508
		}
509
		return result;
510
	}
511

    
512

    
513
	private final Map<String, UUID> languageMapping = new HashMap<String, UUID>();
514

    
515
	private Language getFeatureLanguage(String featureLanguage, TaxonExcelImportState state) {
516
		if (StringUtils.isBlank(featureLanguage)){
517
			return null;
518
		}
519
		UUID languageUuid = languageMapping.get(featureLanguage);
520
		if (languageUuid == null){
521
			Language result = getTermService().getLanguageByIso(featureLanguage);
522
			languageUuid = result.getUuid();
523
			languageMapping.put(featureLanguage, languageUuid);
524
		}
525
		Language result = getLanguage(state, languageUuid, null, null, null);
526
		return result;
527
	}
528

    
529

    
530
	/**
531
	 * @param state
532
	 * @param taxonNameStr
533
	 * @param commonNameStr
534
	 * @param parentId
535
	 */
536
	private void handleCommonName(TaxonExcelImportState state,
537
			String taxonNameStr, String commonNameStr, Taxon acceptedTaxon) {
538
		Language language = getTermService().getLanguageByIso(state.getCurrentRow().getLanguage());
539
		if (language == null && CdmUtils.isNotEmpty(state.getCurrentRow().getLanguage())  ){
540
			String error ="Language is null but shouldn't";
541
			logger.error(error);
542
			throw new IllegalArgumentException(error);
543
		}
544
		CommonTaxonName commonTaxonName = CommonTaxonName.NewInstance(commonNameStr, language);
545
		try {
546
			TaxonDescription taxonDescription = getTaxonDescription(acceptedTaxon, false, true);
547
			taxonDescription.addElement(commonTaxonName);
548
			logger.info("Common name " + commonNameStr + " added to " + acceptedTaxon.getTitleCache());
549
		} catch (ClassCastException ex) {
550
			logger.error(taxonNameStr + " is not a taxon instance.");
551
		}
552
	}
553

    
554

    
555
	/**
556
	 * @param state
557
	 * @param rank
558
	 * @param taxonNameStr
559
	 * @param authorStr
560
	 * @param nameStatus
561
	 * @param nameStatus2
562
	 * @return
563
	 */
564
	private TaxonBase createTaxon(TaxonExcelImportState state, Rank rank,
565
			String taxonNameStr, String authorStr, String reference, String date, String nameStatus) {
566
		// Create the taxon name object depending on the setting of the nomenclatural code
567
		// in the configurator (botanical code, zoological code, etc.)
568
		if (StringUtils.isBlank(taxonNameStr)){
569
			return null;
570
		}
571
		NomenclaturalCode nc = getConfigurator().getNomenclaturalCode();
572

    
573
		TaxonBase taxonBase;
574

    
575
		String titleCache = CdmUtils.concat(" ", taxonNameStr, authorStr);
576
		if (! synonymMarkers.contains(nameStatus)  && state.getConfig().isReuseExistingTaxaWhenPossible()){
577
			titleCache = CdmUtils.concat(" ", taxonNameStr, authorStr);
578
			taxonBase = getTaxonService().findBestMatchingTaxon(titleCache);
579
		}else{
580
			taxonBase = getTaxonService().findBestMatchingSynonym(titleCache);
581
			if (taxonBase != null){
582
				logger.info("Matching taxon/synonym found for " + titleCache);
583
			}
584
		}
585
		if (taxonBase != null){
586
			logger.info("Matching taxon/synonym found for " + titleCache);
587
			return null;
588
		}else {
589
			taxonBase = createTaxon(state, rank, taxonNameStr, authorStr, reference, date, nameStatus, nc);
590
		}
591
		return taxonBase;
592
	}
593

    
594

    
595

    
596

    
597
	/**
598
	 * @param state
599
	 * @param rank
600
	 * @param taxonNameStr
601
	 * @param authorStr
602
	 * @param nameStatus
603
	 * @param nameStatus2
604
	 * @param nc
605
	 * @return
606
	 */
607
	private TaxonBase<?> createTaxon(TaxonExcelImportState state, Rank rank, String taxonNameStr,
608
			String authorStr, String reference, String date, String nameStatus, NomenclaturalCode nc) {
609
		TaxonBase<?> taxonBase;
610
		NonViralName<?> taxonNameBase = null;
611
		if (nc == NomenclaturalCode.ICVCN){
612
			logger.warn("ICVCN not yet supported");
613

    
614
		}else{
615
			taxonNameBase =(NonViralName<?>) nc.getNewTaxonNameInstance(rank);
616
			//NonViralName nonViralName = (NonViralName)taxonNameBase;
617
			NonViralNameParserImpl parser = NonViralNameParserImpl.NewInstance();
618
			taxonNameBase = parser.parseFullName(taxonNameStr, nc, rank);
619

    
620
			if (! taxonNameBase.getNameCache().equals(taxonNameStr)){
621
				taxonNameBase.setNameCache(taxonNameStr, true);
622
			}
623

    
624
			// Create the author
625
			if (StringUtils.isNotBlank(authorStr)) {
626
				try {
627
					parser.parseAuthors(taxonNameBase, authorStr);
628
				} catch (StringNotParsableException e) {
629
					taxonNameBase.setAuthorshipCache(authorStr);
630
 				}
631
			}
632
			if (StringUtils.isNotBlank(reference)) {
633

    
634
			    INomenclaturalReference ref = parser.parseReferenceTitle(reference, date, false);
635
			    if (ref.getAuthorship() == null){
636
			        ref.setAuthorship(taxonNameBase.getCombinationAuthorship());
637
			    }
638
			    if (ref.getAbbrevTitle() == null){
639
			        ref.setAbbrevTitle(reference);
640
			    }
641
			    ref.setProtectedAbbrevTitleCache(false);
642
			    ref.setProtectedTitleCache(false);
643

    
644
			    taxonNameBase.setNomenclaturalReference(ref);
645
			}
646
		}
647

    
648
		//Create the taxon
649
		Reference sec = state.getConfig().getSourceReference();
650
		// Create the status
651
		nameStatus = CdmUtils.Nz(nameStatus).trim().toLowerCase();
652
		if (validMarkers.contains(nameStatus)){
653
			taxonBase = Taxon.NewInstance(taxonNameBase, sec);
654
		}else if (synonymMarkers.contains(nameStatus)){
655
			taxonBase = Synonym.NewInstance(taxonNameBase, sec);
656
		}else {
657
			Taxon taxon = Taxon.NewInstance(taxonNameBase, sec);
658
			if (nameStatusMarkers.contains(nameStatus)){
659
			    if (nameStatus.equals(NOM_ILLEG)){
660
			        taxonNameBase.addStatus(NomenclaturalStatusType.ILLEGITIMATE(), null, null);
661
			    } else if (nameStatus.equals(NOM_REJ)){
662
			        taxonNameBase.addStatus(NomenclaturalStatusType.REJECTED(), null, null);
663
			    } else if (nameStatus.equals(NOM_CONS)){
664
                    taxonNameBase.addStatus(NomenclaturalStatusType.CONSERVED(), null, null);
665
                }
666
			}else{
667
			    taxon.setTaxonStatusUnknown(true);
668
			}
669
			taxonBase = taxon;
670
		}
671
		return taxonBase;
672
	}
673

    
674
	/**
675
	 * @param taxon
676
	 * @return
677
	 */
678
	//TODO implementation must be improved when matching of taxon names with existing names is implemented
679
	//=> the assumption that the only description is the description added by this import
680
	//is wrong then
681
	private TaxonNameDescription getNameDescription(TaxonNameBase<?,?> name) {
682
		Set<TaxonNameDescription> descriptions = name.getDescriptions();
683
		if (descriptions.size()>1){
684
			throw new IllegalStateException("Implementation does not yet support names with multiple descriptions");
685
		}else if (descriptions.size()==1){
686
			return descriptions.iterator().next();
687
		}else{
688
			return TaxonNameDescription.NewInstance(name);
689
		}
690
	}
691

    
692
	private void makeParent(TaxonExcelImportState state, Taxon parentTaxon, Taxon childTaxon, Reference citation, String microCitation){
693
		Reference sec = state.getConfig().getSourceReference();
694

    
695
//		Reference sec = parentTaxon.getSec();
696
		Classification tree = state.getClassification();
697
		if (tree == null){
698
			//tree = makeTree(state, sec);
699
		    if (state.getConfig().getClassificationUuid() != null){
700
		        tree = getClassificationService().load(state.getConfig().getClassificationUuid());
701
		        state.setClassification(tree);
702
		    }
703
		    if (tree == null){
704
		        tree = makeTree(state, sec);
705
		        getClassificationService().save(tree);
706
		        state.setClassification(tree);
707
		    }
708
		}
709
		if (sec.equals(childTaxon.getSec())){
710
		    boolean success =  (null !=  tree.addParentChild(parentTaxon, childTaxon, citation, microCitation));
711
			if (success == false){
712
				state.setUnsuccessfull();
713
			}
714
		}else{
715
			logger.warn("No relationship added for child " + childTaxon.getTitleCache());
716
		}
717
		return;
718
	}
719

    
720

    
721
	/* (non-Javadoc)
722
	 * @see eu.etaxonomy.cdm.io.excel.common.ExcelTaxonOrSpecimenImportBase#createDataHolderRow()
723
	 */
724
	@Override
725
	protected NormalExplicitRow createDataHolderRow() {
726
		return new NormalExplicitRow();
727
	}
728

    
729

    
730

    
731
	/* (non-Javadoc)
732
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IoStateBase)
733
	 */
734
	@Override
735
	protected boolean doCheck(TaxonExcelImportState state) {
736
		logger.warn("DoCheck not yet implemented for NormalExplicitImport");
737
		return true;
738
	}
739

    
740
	/* (non-Javadoc)
741
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IoStateBase)
742
	 */
743
	@Override
744
	protected boolean isIgnore(TaxonExcelImportState state) {
745
		return false;
746
	}
747

    
748

    
749

    
750
}
(1-1/5)