Project

General

Profile

Download (36.2 KB) Statistics
| Branch: | 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.redlist.bfnXml.in;
11

    
12
import java.util.ArrayList;
13
import java.util.Collection;
14
import java.util.LinkedHashMap;
15
import java.util.List;
16
import java.util.Map;
17
import java.util.UUID;
18

    
19
import org.apache.commons.lang.StringUtils;
20
import org.apache.log4j.Logger;
21
import org.jdom.Element;
22
import org.jdom.Namespace;
23
import org.springframework.stereotype.Component;
24
import org.springframework.transaction.TransactionStatus;
25

    
26
import eu.etaxonomy.cdm.api.service.IClassificationService;
27
import eu.etaxonomy.cdm.api.service.ITaxonService;
28
import eu.etaxonomy.cdm.common.ResultWrapper;
29
import eu.etaxonomy.cdm.common.XmlHelp;
30
import eu.etaxonomy.cdm.io.redlist.bfnXml.BfnXmlConstants;
31
import eu.etaxonomy.cdm.model.common.CdmBase;
32
import eu.etaxonomy.cdm.model.common.DefinedTermBase;
33
import eu.etaxonomy.cdm.model.common.Language;
34
import eu.etaxonomy.cdm.model.common.TermVocabulary;
35
import eu.etaxonomy.cdm.model.description.CategoricalData;
36
import eu.etaxonomy.cdm.model.description.CommonTaxonName;
37
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
38
import eu.etaxonomy.cdm.model.description.Distribution;
39
import eu.etaxonomy.cdm.model.description.Feature;
40
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
41
import eu.etaxonomy.cdm.model.description.State;
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.name.NomenclaturalCode;
46
import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
47
import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
48
import eu.etaxonomy.cdm.model.name.NonViralName;
49
import eu.etaxonomy.cdm.model.name.Rank;
50
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
51
import eu.etaxonomy.cdm.model.reference.Reference;
52
import eu.etaxonomy.cdm.model.taxon.Classification;
53
import eu.etaxonomy.cdm.model.taxon.Synonym;
54
import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
55
import eu.etaxonomy.cdm.model.taxon.Taxon;
56
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
57
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
58
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
59
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
60
import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
61
import eu.etaxonomy.cdm.strategy.parser.ParserProblem;
62
/**
63
 *
64
 * @author a.oppermann
65
 * @date 04.07.2013
66
 *
67
 */
68
//@Component("bfnXmlTaxonNameIO")
69
@Component
70
public class BfnXmlImportTaxonName extends BfnXmlImportBase {
71

    
72
    private static final Logger logger = Logger.getLogger(BfnXmlImportTaxonName.class);
73

    
74
	private static NomenclaturalCode nomenclaturalCode = null;
75
	private static int parsingProblemCounter = 0;
76
	private Map<Integer, Taxon> firstList;
77
	private Map<Integer, Taxon> secondList;
78

    
79

    
80
	public BfnXmlImportTaxonName(){
81
		super();
82
	}
83

    
84

    
85
	@Override
86
	@SuppressWarnings({"rawtypes" })
87
	public void doInvoke(BfnXmlImportState state){
88
		ITaxonService taxonService = getTaxonService();
89

    
90
		BfnXmlImportConfigurator config = state.getConfig();
91
		nomenclaturalCode = config.getNomenclaturalCode();
92
		Element elDataSet = getDataSetElement(config);
93
		//TODO set Namespace
94
		Namespace bfnNamespace = config.getBfnXmlNamespace();
95

    
96
		List<?> contentXML = elDataSet.getContent();
97
		Element currentElement = null;
98
		for(Object object:contentXML){
99

    
100
			if(object instanceof Element){
101
				currentElement = (Element)object;
102
				//import taxon lists
103
				if(currentElement.getName().equalsIgnoreCase(BfnXmlConstants.EL_ROTELISTEDATEN)){
104
					TransactionStatus tx = startTransaction();
105
					Map<UUID, TaxonBase> savedTaxonMap = extractTaxonNames(state, taxonService, config, currentElement, bfnNamespace);
106
					createOrUpdateClassification(config, taxonService, savedTaxonMap, currentElement, state);
107
					commitTransaction(tx);
108
				}//import concept relations of taxon lists
109
				if(config.isHasSecondList()){
110
					if(currentElement.getName().equalsIgnoreCase(BfnXmlConstants.EL_KONZEPTBEZIEHUNGEN)){
111
						TransactionStatus tx = startTransaction();
112
						extractTaxonConceptRelationShips(bfnNamespace,currentElement);
113
						commitTransaction(tx);
114
					}
115
				}
116
			}
117
		}
118
		return;
119
	}
120

    
121
	/**
122
	 * This method will parse the XML concept relationships and tries to map them into cdm relationship types.
123
	 *
124
	 * @param bfnNamespace
125
	 * @param currentElement
126
	 */
127
	private void extractTaxonConceptRelationShips(Namespace bfnNamespace, Element currentElement) {
128
		String childName;
129
		String bfnElementName = BfnXmlConstants.EL_KONZEPTBEZIEHUNG;
130
		ResultWrapper<Boolean> success = ResultWrapper.NewInstance(true);
131
		List<Element> elConceptList = currentElement.getChildren(bfnElementName, bfnNamespace);
132
		List<TaxonBase> updatedTaxonList = new ArrayList<TaxonBase>();
133
		for(Element element:elConceptList){
134

    
135
			childName = "TAXONYM1";
136
			Element elTaxon1 = XmlHelp.getSingleChildElement(success, element, childName, bfnNamespace, false);
137
			String taxNr1 = elTaxon1.getAttributeValue(BfnXmlConstants.ATT_TAXNR);
138
			int int1 = Integer.parseInt(taxNr1);
139
			Taxon taxon1 = firstList.get(int1);
140
			TaxonBase<?> taxonBase1 = getTaxonService().load(taxon1.getUuid());
141
			taxon1 = (Taxon)taxonBase1;
142

    
143
			childName = "TAXONYM2";
144
			Element elTaxon2 = XmlHelp.getSingleChildElement(success, element, childName, bfnNamespace, false);
145
			String taxNr2 = elTaxon2.getAttributeValue(BfnXmlConstants.ATT_TAXNR);
146
			int int2 = Integer.parseInt(taxNr2);
147
			Taxon taxon2 = secondList.get(int2);
148
			TaxonBase<?> taxonBase2 = getTaxonService().load(taxon2.getUuid());
149
			taxon2 = (Taxon) taxonBase2;
150

    
151
			childName = "STATUS";
152
			Element elConceptStatus = XmlHelp.getSingleChildElement(success, element, childName, bfnNamespace, false);
153
			String conceptStatusValue = elConceptStatus.getValue();
154
			conceptStatusValue = conceptStatusValue.replaceAll("\u00A0", "").trim();
155
			TaxonRelationshipType taxonRelationType = null;
156
			/**
157
			 * This if case only exists because it was decided not to have a included_in relationship type.
158
			 */
159
			if(conceptStatusValue.equalsIgnoreCase("<")){
160
				taxon2.addTaxonRelation(taxon1, TaxonRelationshipType.INCLUDES(), null, null);
161
			}else{
162
				taxonRelationType = BfnXmlTransformer.getTaxonRelationForConceptCode(conceptStatusValue);
163
				taxon1.addTaxonRelation(taxon2, taxonRelationType , null, null);
164
			}
165
			if(taxonRelationType != null && taxonRelationType.equals(TaxonRelationshipType.ALL_RELATIONSHIPS())){
166
				List<TaxonRelationship> relationsFromThisTaxon = (List<TaxonRelationship>) taxon1.getRelationsFromThisTaxon();
167
				TaxonRelationship taxonRelationship = relationsFromThisTaxon.get(0);
168
				taxonRelationship.setDoubtful(true);
169
			}
170
			updatedTaxonList.add(taxon2);
171
			updatedTaxonList.add(taxon1);
172
		}
173
		getTaxonService().saveOrUpdate(updatedTaxonList);
174
		logger.info("taxon relationships imported...");
175
	}
176

    
177
	/**
178
	 * This method stores the current imported maps in global variables to make
179
	 * them later available for matching the taxon relationships between these
180
	 * imported lists.
181
	 *
182
	 * @param config
183
	 * @param taxonMap
184
	 */
185
	private void prepareListforConceptImport(BfnXmlImportConfigurator config,Map<Integer, Taxon> taxonMap) {
186
		if(config.isFillSecondList()){
187
			secondList = taxonMap;
188
		}else{
189
			firstList = taxonMap;
190
		}
191
	}
192

    
193
	/**
194
	 *
195
	 * @param state
196
	 * @param taxonService
197
	 * @param config
198
	 * @param elDataSet
199
	 * @param bfnNamespace
200
	 * @return
201
	 */
202
	private Map<UUID, TaxonBase> extractTaxonNames(BfnXmlImportState state,
203
			ITaxonService taxonService, BfnXmlImportConfigurator config,
204
			Element elDataSet, Namespace bfnNamespace) {
205
		logger.info("start make TaxonNames...");
206
		Map<Integer, Taxon> taxonMap = new LinkedHashMap<Integer, Taxon>();
207
		ResultWrapper<Boolean> success = ResultWrapper.NewInstance(true);
208
		String childName;
209
		boolean obligatory;
210
		String idNamespace = "TaxonName";
211

    
212
		childName = BfnXmlConstants.EL_TAXONYME;
213
		obligatory = false;
214
		Element elTaxonNames = XmlHelp.getSingleChildElement(success, elDataSet, childName, bfnNamespace, obligatory);
215

    
216
		String bfnElementName = BfnXmlConstants.EL_TAXONYM;
217
		List<Element> elTaxonList = elTaxonNames.getChildren(bfnElementName, bfnNamespace);
218

    
219
		//for each taxonName
220
		for (Element elTaxon : elTaxonList){
221
			//create Taxon
222
			String taxonId = elTaxon.getAttributeValue(BfnXmlConstants.ATT_TAXNR);
223
			childName = BfnXmlConstants.EL_WISSNAME;
224
			Element elWissName = XmlHelp.getSingleChildElement(success, elTaxon, childName, bfnNamespace, obligatory);
225
			String childElementName = BfnXmlConstants.EL_NANTEIL;
226
			Taxon taxon = createOrUpdateTaxon(success, taxonId, config, bfnNamespace, elWissName, childElementName, state);
227

    
228
			//for each synonym
229
			childName = "SYNONYME";
230
			Element elSynonyms = XmlHelp.getSingleChildElement(success, elTaxon, childName, bfnNamespace, obligatory);
231
			if(elSynonyms != null){
232
				childElementName = "SYNONYM";
233
				createOrUpdateSynonym(taxon, success, obligatory, bfnNamespace, childElementName,elSynonyms, taxonId, state);
234
			}
235
			//for vernacular name
236
			childName = BfnXmlConstants.EL_DEUTSCHENAMEN;
237
			Element elVernacularName = XmlHelp.getSingleChildElement(success, elTaxon, childName, bfnNamespace, obligatory);
238
			if(elVernacularName != null){
239
				childElementName = BfnXmlConstants.EL_DNAME;
240
				createOrUpdateVernacularName(taxon, bfnNamespace, childElementName, elVernacularName, state);
241
			}
242
			//for each information concerning the taxon element
243
			//TODO Information block
244
			if(config.isDoInformationImport()){
245
				childName = BfnXmlConstants.EL_INFORMATIONEN;
246
				Element elInformations = XmlHelp.getSingleChildElement(success, elTaxon, childName, bfnNamespace, obligatory);
247
				if(elInformations != null){
248
					childElementName = BfnXmlConstants.EL_BEZUGSRAUM;
249
					createOrUpdateInformation(taxon, bfnNamespace, childElementName,elInformations, state);
250
				}
251
			}
252
			taxonMap.put(Integer.parseInt(taxonId), taxon);
253
		}
254

    
255
		//Quick'n'dirty to set concept relationships between two imported list
256
		prepareListforConceptImport(config, taxonMap);
257

    
258
		Map<UUID, TaxonBase> savedTaxonMap = taxonService.saveOrUpdate((Collection)taxonMap.values());
259
		//FIXME: after first list don't import metadata yet
260
		//TODO: import information for second taxon list.
261
		config.setDoInformationImport(false);
262
		logger.info("end makeTaxonNames ...");
263
		if (!success.getValue()){
264
			state.setUnsuccessfull();
265
		}
266
		return savedTaxonMap;
267
	}
268

    
269

    
270

    
271

    
272
	/**
273
	 * This will put the prior imported list into a classification
274
	 *
275
	 * @param config
276
	 * @param taxonService
277
	 * @param config
278
	 * @param savedTaxonMap
279
	 * @param currentElement
280
	 * @param state
281
	 * @return
282
	 */
283
	@SuppressWarnings("rawtypes")
284
	private boolean createOrUpdateClassification(BfnXmlImportConfigurator config, ITaxonService taxonService, Map<UUID, TaxonBase> savedTaxonMap, Element currentElement, BfnXmlImportState state) {
285
		boolean isNewClassification = true;
286
		Classification classification = Classification.NewInstance(currentElement.getAttributeValue("inhalt"), state.getCompleteSourceRef());
287
		//TODO do we really want toString() or titleCache here?
288
		String microRef = state.getCurrentMicroRef() == null ? null : state.getCurrentMicroRef().toString();
289
		classification.addImportSource(Integer.toString(classification.getId()), classification.getTitleCache(), state.getCompleteSourceRef(), microRef);
290
//		List<Classification> classificationList = getClassificationService().list(Classification.class, null, null, null, VOC_CLASSIFICATION_INIT_STRATEGY);
291
//		for(Classification c : classificationList){
292
//			if(c.getTitleCache().equalsIgnoreCase(classification.getTitleCache())){
293
//				classification = c;
294
//				isNewClassification = false;
295
//			}
296
//		}
297

    
298
//		ArrayList<TaxonBase> taxonBaseList = (ArrayList<TaxonBase>) taxonService.list(TaxonBase.class, null, null, null, VOC_CLASSIFICATION_INIT_STRATEGY);
299
		for(TaxonBase tb:savedTaxonMap.values()){
300
			if(tb instanceof Taxon){
301
				TaxonBase tbase = CdmBase.deproxy(tb, TaxonBase.class);
302
				Taxon taxon = (Taxon)tbase;
303
				taxon = CdmBase.deproxy(taxon, Taxon.class);
304
				classification.addChildTaxon(taxon, null, null);
305
			}
306
		}
307
		IClassificationService classificationService = getClassificationService();
308
		classificationService.saveOrUpdate(classification);
309
		//set boolean for reference and internal mapping of concept relations
310
		if(config.isHasSecondList()){
311
			config.setFillSecondList(true);
312
		}
313
		return isNewClassification;
314
	}
315

    
316

    
317

    
318
	/**
319
	 * Matches the XML attributes against CDM entities.<BR>
320
	 * Imports Scientific Name, Rank, etc. and creates a taxon.<br>
321
	 * <b>Existing taxon names won't be matched yet</b>
322
	 *
323
	 * @param success
324
	 * @param taxonId
325
	 * @param config
326
	 * @param bfnNamespace
327
	 * @param elTaxonName
328
	 * @param childElementName
329
	 * @param state
330
	 * @return
331
	 */
332

    
333
	@SuppressWarnings({ "unchecked" })
334
	private Taxon createOrUpdateTaxon(
335
			ResultWrapper<Boolean> success, String taxonId,
336
			BfnXmlImportConfigurator config, Namespace bfnNamespace,
337
			Element elTaxonName, String childElementName, BfnXmlImportState state) {
338

    
339
		List<Element> elWissNameList = elTaxonName.getChildren(childElementName, bfnNamespace);
340
		Rank rank = null;
341
		String strAuthor = null;
342
		String strSupplement = null;
343
		Taxon taxon = null;
344
		String uniqueID = null;
345
		String uriNameSpace = null;
346
//		Long uniqueID = null;
347
		for(Element elWissName:elWissNameList){
348

    
349
			if(elWissName.getAttributeValue(BfnXmlConstants.ATT_BEREICH, bfnNamespace).equalsIgnoreCase("Eindeutiger Code")){
350
				uriNameSpace = elWissName.getAttributeValue(BfnXmlConstants.ATT_BEREICH);
351
				String textNormalize = elWissName.getTextNormalize();
352
				if(StringUtils.isBlank(textNormalize)){
353
					uniqueID = "";
354
				}else{
355
					uniqueID = textNormalize;
356
				}
357
			}
358
			if(elWissName.getAttributeValue(BfnXmlConstants.ATT_BEREICH, bfnNamespace).equalsIgnoreCase("Autoren")){
359
				strAuthor = elWissName.getTextNormalize();
360
			}
361
			if(elWissName.getAttributeValue(BfnXmlConstants.ATT_BEREICH, bfnNamespace).equalsIgnoreCase("Rang")){
362
				String strRank = elWissName.getTextNormalize();
363
				rank = makeRank(strRank);
364
			}
365
			if(elWissName.getAttributeValue(BfnXmlConstants.ATT_BEREICH, bfnNamespace).equalsIgnoreCase("Zusätze")){
366
				strSupplement = elWissName.getTextNormalize();
367
			}
368
			if(elWissName.getAttributeValue(BfnXmlConstants.ATT_BEREICH, bfnNamespace).equalsIgnoreCase("wissName")){
369
				try{
370
					TaxonNameBase<?, ?> nameBase = parseNonviralNames(rank,strAuthor,strSupplement,elWissName);
371
					if(nameBase.isProtectedTitleCache() == true){
372
						logger.warn("Taxon " + nameBase.getTitleCache());
373
					}
374

    
375
					//TODO  extract to method?
376
					if(strSupplement != null){
377
						nameBase.setAppendedPhrase(strSupplement);
378
					}
379
					if(strSupplement != null && strSupplement.equalsIgnoreCase("nom. illeg.")){
380
						nameBase.addStatus(NomenclaturalStatus.NewInstance(NomenclaturalStatusType.ILLEGITIMATE()));
381
					}
382
					/**
383
					 *  BFN does not want any name matching yet
384
					 */
385
//					TaxonBase<?> taxonBase = null;
386
//					//TODO find best matching Taxa
387
//					Pager<TaxonNameBase> names = getNameService().findByTitle(null, nameBase.getTitleCache(), null, null, null, null, null, null);
388
//					//TODO  correct handling for pager
389
//					List<TaxonNameBase> nameList = names.getRecords();
390
//					if (nameList.isEmpty()){
391
//						taxonBase = Taxon.NewInstance(nameBase, config.getSourceReference());
392
//					}else{
393
//						taxonBase = Taxon.NewInstance(nameList.get(0), config.getSourceReference());
394
//						if (nameList.size()>1){
395
//							logger.warn("More than 1 matching taxon name found for " + nameBase.getTitleCache());
396
//						}
397
//					}
398

    
399
					Reference<?> microRef = config.isFillSecondList() ?
400
					        state.getSecondListSecRef():
401
					        state.getFirstListSecRef();
402
					state.setCurrentMicroRef(microRef);
403
					taxon = Taxon.NewInstance(nameBase, state.getCurrentMicroRef());
404
					//set create and set path of nameSpace
405
					Element parentElement = elWissName.getParentElement();
406
					Element grandParentElement = parentElement.getParentElement();
407
					String namespace = grandParentElement.getName() + ":" + parentElement.getName() + ":"+elWissName.getName() + ":" + uriNameSpace;
408
					String microRefStr = microRef == null ? null : microRef.getTitle();
409
					taxon.addImportSource(uniqueID, namespace, state.getCompleteSourceRef(), microRefStr);
410

    
411
					taxon.addIdentifier(taxonId, getIdentiferType(state, BfnXmlConstants.UUID_TAX_NR_IDENTIFIER_TYPE, "taxNr", "TaxNr attribute of Bfn Xml file", "taxNr", null));
412
				} catch (UnknownCdmTypeException e) {
413
					success.setValue(false);
414
				}
415
			}
416
		}
417
		return taxon;
418
	}
419

    
420
	/**
421
	 * Matches the XML attributes against CDM entities.<BR>
422
	 * Imports Scientific Name, Rank etc. and create a synonym.<br>
423
	 * <b>Existing synonym names won't be matched yet</b>
424
	 *
425
	 * @param taxon
426
	 * @param success
427
	 * @param obligatory
428
	 * @param bfnNamespace
429
	 * @param childElementName
430
	 * @param elSynonyms
431
	 * @param taxonId
432
	 * @param config
433
	 * @param state
434
	 */
435

    
436
	@SuppressWarnings({ "unchecked" })
437
	private void createOrUpdateSynonym(Taxon taxon, ResultWrapper<Boolean> success, boolean obligatory, Namespace bfnNamespace,
438
			     String childElementName, Element elSynonyms, String taxonId, BfnXmlImportState state) {
439

    
440
		String childName;
441
		List<Element> elSynonymList = elSynonyms.getChildren(childElementName, bfnNamespace);
442

    
443
		for(Element elSyn:elSynonymList){
444
			Rank rank = null;
445
			String strAuthor = null;
446
			String strSupplement = null;
447
			childName = BfnXmlConstants.EL_WISSNAME;
448
			Element elSynScientificName = XmlHelp.getSingleChildElement(success, elSyn, childName, bfnNamespace, obligatory);
449

    
450
			childElementName = BfnXmlConstants.EL_NANTEIL;
451
			List<Element> elSynDetails = elSynScientificName.getChildren(childElementName, bfnNamespace);
452

    
453
			for(Element elSynDetail:elSynDetails){
454
				if(elSynDetail.getAttributeValue(BfnXmlConstants.ATT_BEREICH).equalsIgnoreCase("Rang")){
455
					String strRank = elSynDetail.getTextNormalize();
456
					rank = makeRank(strRank);
457
				}
458
				if(elSynDetail.getAttributeValue(BfnXmlConstants.ATT_BEREICH).equalsIgnoreCase("Autoren")){
459
					strAuthor = elSynDetail.getTextNormalize();
460
				}
461
				if(elSynDetail.getAttributeValue(BfnXmlConstants.ATT_BEREICH, bfnNamespace).equalsIgnoreCase("Zusätze")){
462
					strSupplement = elSynDetail.getTextNormalize();
463
				}
464
				if(elSynDetail.getAttributeValue(BfnXmlConstants.ATT_BEREICH).equalsIgnoreCase("wissName")){
465
					try{
466
						TaxonNameBase<?, ?> nameBase = parseNonviralNames(rank,strAuthor,strSupplement,elSynDetail);
467

    
468
						//TODO find best matching Taxa
469
						Synonym synonym = Synonym.NewInstance(nameBase, state.getCurrentMicroRef());
470
						taxon.addSynonym(synonym, SynonymRelationshipType.SYNONYM_OF());
471

    
472
					} catch (UnknownCdmTypeException e) {
473
						logger.warn("Name with id " + taxonId + " has unknown nomenclatural code.");
474
						success.setValue(false);
475
					}
476

    
477
				}
478

    
479
			}
480
		}
481
	}
482

    
483

    
484
	/**
485
	 *
486
	 * @param taxon
487
	 * @param bfnNamespace
488
	 * @param childElementName
489
	 * @param elVernacularName
490
	 * @param state
491
	 */
492
	private void createOrUpdateVernacularName(Taxon taxon,
493
			Namespace bfnNamespace, String childElementName,
494
			Element elVernacularName, BfnXmlImportState state) {
495

    
496
		List<Element> elVernacularNameList = elVernacularName.getChildren(childElementName, bfnNamespace);
497

    
498
		TaxonDescription taxonDescription = getTaxonDescription(taxon, false, true);
499

    
500
		for(Element elVernacular : elVernacularNameList){
501
			Element child = elVernacular.getChild("TRIVIALNAME");
502
			if(child != null){
503
				makeCommonName(taxonDescription, child, state);
504
			}
505
		}
506

    
507
	}
508

    
509
	/**
510
	 *
511
	 * @param taxon
512
	 * @param bfnNamespace
513
	 * @param childElementName
514
	 * @param elInformations
515
	 * @param state
516
	 * @throws UnknownCdmTypeException
517
	 */
518

    
519
	@SuppressWarnings("unchecked")
520
	private void createOrUpdateInformation(Taxon taxon,
521
			Namespace bfnNamespace, String childElementName,
522
			Element elInformations,
523
			BfnXmlImportState state){
524

    
525
		List<Element> elInformationList = elInformations.getChildren(childElementName, bfnNamespace);
526

    
527
		for(Element elInfo:elInformationList){
528
			//check if geographical scope is Bund and import only these information for now
529
			//TODO create several taxon descriptions for different geographical scope
530
			if(elInfo.getName().equalsIgnoreCase(BfnXmlConstants.EL_BEZUGSRAUM) && elInfo.getAttributeValue("name").equalsIgnoreCase("Bund")){
531
				childElementName = BfnXmlConstants.EL_IWERT;
532
				TaxonDescription taxonDescription = getTaxonDescription(taxon, false, true);
533
				UUID germanStateUUID;
534
				try {
535
					germanStateUUID = BfnXmlTransformer.getGermanStateUUID("Deutschland");
536
					NamedArea area = (NamedArea)getTermService().load(germanStateUUID);
537
					//FIXME GEOSCOPE_ID CANNOT BE NULL Exception
538
//					taxonDescription.addGeoScope(area);
539
				} catch (UnknownCdmTypeException e) {
540
					// TODO Auto-generated catch block
541
					e.printStackTrace();
542
				}
543
				List<Element> elInfoDetailList = elInfo.getChildren(childElementName, bfnNamespace);
544

    
545
				for(Element elInfoDetail : elInfoDetailList){
546
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("RL Kat.")){
547
						makeFeatures(taxonDescription, elInfoDetail, state, false);
548
					}
549
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("Kat. +/-")){
550
						makeFeatures(taxonDescription, elInfoDetail, state, false);
551
					}
552
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("aktuelle Bestandsstituation")){
553
						makeFeatures(taxonDescription, elInfoDetail, state, false);
554
					}
555
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("langfristiger Bestandstrend")){
556
						makeFeatures(taxonDescription, elInfoDetail, state, false);
557
					}
558
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("kurzfristiger Bestandstrend")){
559
						makeFeatures(taxonDescription, elInfoDetail, state, false);
560
					}
561
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("Risikofaktoren")){
562
						makeFeatures(taxonDescription, elInfoDetail, state, false);
563
					}
564
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("Verantwortlichkeit")){
565
						makeFeatures(taxonDescription, elInfoDetail, state, false);
566
					}
567
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("alte RL- Kat.")){
568
						makeFeatures(taxonDescription, elInfoDetail, state, false);
569
					}
570
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("Neobiota")){
571
						makeFeatures(taxonDescription, elInfoDetail, state, false);
572
					}
573
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("Eindeutiger Code")){
574
						makeFeatures(taxonDescription, elInfoDetail, state, false);
575
					}
576
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("Kommentar zur Taxonomie")){
577
						makeFeatures(taxonDescription, elInfoDetail, state, true);
578
					}
579
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("Kommentar zur Gefährdung")){
580
						makeFeatures(taxonDescription, elInfoDetail, state, true);
581
					}
582
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("Sonderfälle")){
583
						makeFeatures(taxonDescription, elInfoDetail, state, false);
584
					}
585
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("Letzter Nachweis")){
586
						makeFeatures(taxonDescription, elInfoDetail, state, true);
587
					}
588
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("Weitere Kommentare")){
589
						makeFeatures(taxonDescription, elInfoDetail, state, true);
590
					}
591
					//create german federal states distribution status
592
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("BW")){
593
                        createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
594
                    }
595
					//create german federal states distribution status
596
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("BY")){
597
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
598
					}
599
					//create german federal states distribution status
600
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("BE")){
601
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
602
					}
603
					//create german federal states distribution status
604
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("BB")){
605
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
606
					}
607
					//create german federal states distribution status
608
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("HB")){
609
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
610
					}
611
					//create german federal states distribution status
612
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("HH")){
613
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
614
					}
615
					//create german federal states distribution status
616
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("HE")){
617
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
618
					}
619
					//create german federal states distribution status
620
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("MV")){
621
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
622
					}
623
					//create german federal states distribution status
624
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("NI")){
625
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
626
					}
627
					//create german federal states distribution status
628
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("NW")){
629
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
630
					}
631
					//create german federal states distribution status
632
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("RP")){
633
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
634
					}
635
					//create german federal states distribution status
636
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("SL")){
637
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
638
					}
639
					//create german federal states distribution status
640
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("SN")){
641
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
642
					}
643
					//create german federal states distribution status
644
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("ST")){
645
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
646
					}
647
					//create german federal states distribution status
648
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("SH")){
649
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
650
					}
651
					//create german federal states distribution status
652
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("TH")){
653
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
654
					}
655
				}
656
			}
657
		}
658
	}
659

    
660

    
661
    private void makeCommonName(TaxonDescription taxonDescription,
662
			Element child, BfnXmlImportState state) {
663
		String commonNameValue = child.getValue();
664
		NamedArea area = getTermService().getAreaByTdwgAbbreviation("GER");
665
		CommonTaxonName commonName = CommonTaxonName.NewInstance(commonNameValue, Language.GERMAN(), area);
666
		taxonDescription.addElement(commonName);
667
	}
668

    
669

    
670
	/**
671
	 *
672
	 * @param taxonDescription
673
	 * @param elInfoDetail
674
	 * @param state
675
	 * @param isTextData
676
	 */
677
	private void makeFeatures(
678
			TaxonDescription taxonDescription,
679
			Element elInfoDetail,
680
			BfnXmlImportState state,
681
			boolean isTextData) {
682

    
683
		String transformedRlKatValue = null;
684
		UUID featureUUID = null;
685
		UUID stateTermUUID = null;
686
		String strRlKatValue = elInfoDetail.getChild(BfnXmlConstants.EL_WERT).getValue();
687
		String strRlKat = elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME);
688
		boolean randomStateUUID = false;
689
		try {
690
			featureUUID = BfnXmlTransformer.getRedlistFeatureUUID(strRlKat);
691
			transformedRlKatValue = BfnXmlTransformer.redListString2RedListCode(strRlKatValue);
692
		} catch (UnknownCdmTypeException e) {
693
			transformedRlKatValue = strRlKatValue;
694
		}
695
		Feature redListFeature = getFeature(state, featureUUID);
696
		State rlState = null;
697
		//if is text data a state is not needed
698
		if(!isTextData){
699
			try {
700
				stateTermUUID = BfnXmlTransformer.getRedlistStateTermUUID(transformedRlKatValue, strRlKat);
701
			} catch (UnknownCdmTypeException e) {
702
				stateTermUUID = UUID.randomUUID();
703
				randomStateUUID = true;
704
			}
705
			if(randomStateUUID || stateTermUUID == BfnXmlConstants.stateTermEmpty){
706
				if(stateTermUUID == BfnXmlConstants.stateTermEmpty) {
707
                    transformedRlKatValue = "keine Angabe";
708
                }
709
				rlState = getStateTerm(state, stateTermUUID, transformedRlKatValue, transformedRlKatValue, transformedRlKatValue, null);
710
			}else{
711
				rlState = getStateTerm(state, stateTermUUID);
712
			}
713
		}
714
		if(isTextData){
715
			TextData textData = TextData.NewInstance(redListFeature);
716
			textData.putText(Language.GERMAN(), strRlKatValue);
717
			DescriptionElementBase descriptionElement = textData;
718
			taxonDescription.addElement(descriptionElement);
719
		}else{
720
			CategoricalData catData = CategoricalData.NewInstance(rlState, redListFeature);
721
			DescriptionElementBase descriptionElement = catData;
722
			taxonDescription.addElement(descriptionElement);
723
		}
724
	}
725

    
726
	/**
727
	 * Returns the rank represented by the rank element.<br>
728
	 * Returns <code>null</code> if the element is null.<br>
729
	 * Returns <code>null</code> if the code and the text are both either empty or do not exists.<br>
730
	 * Returns the rank represented by the code attribute, if the code attribute is not empty and could be resolved.<br>
731
	 * If the code could not be resolved it returns the rank represented most likely by the elements text.<br>
732
	 * Returns UNKNOWN_RANK if code attribute and element text could not be resolved.
733
	 * @param strRank bfn rank element
734
	 * @return
735
	 */
736
	protected static Rank makeRank(String strRank){
737
		Rank result;
738
 		if (strRank == null){
739
			return null;
740
		}
741
		Rank codeRank = BfnXmlTransformer.getRankForRankCode(strRank);
742
		if(codeRank==null){
743
		    codeRank = Rank.UNKNOWN_RANK();
744
		}
745
		//codeRank exists
746
		if ( (codeRank != null) && !codeRank.equals(Rank.UNKNOWN_RANK())){
747
			result = codeRank;
748
		}
749
		//codeRank does not exist
750
		else{
751
			result = codeRank;
752
			logger.warn("string rank used, because code rank does not exist or was not recognized: " + codeRank.getTitleCache()+" "+strRank);
753
		}
754
		return result;
755
	}
756

    
757
	/**
758
	 * @param rank
759
	 * @param strAuthor
760
	 * @param strSupplement
761
	 * @param elWissName
762
	 * @return
763
	 * @throws UnknownCdmTypeException
764
	 */
765
	private TaxonNameBase<?, ?> parseNonviralNames(Rank rank, String strAuthor, String strSupplement, Element elWissName)
766
			throws UnknownCdmTypeException {
767
		TaxonNameBase<?,?> taxonNameBase = null;
768

    
769
		String strScientificName = elWissName.getTextNormalize();
770
		/**
771
		 *
772
		 * trim strScienctificName because sometimes
773
		 * getTextNormalize() does not removes all the
774
		 * whitespaces
775
		 *
776
		 **/
777
		strScientificName = StringUtils.trim(strScientificName);
778
		strScientificName = StringUtils.remove(strScientificName, "\u00a0");
779
		strScientificName = StringUtils.remove(strScientificName, "\uc281");
780

    
781
		if(strSupplement != null && !strSupplement.isEmpty()){
782
			strScientificName = StringUtils.remove(strScientificName, strSupplement);
783
		}
784
		NonViralName<?> nonViralName = null;
785
		NonViralNameParserImpl parser = NonViralNameParserImpl.NewInstance();
786
		nonViralName = parser.parseFullName(strScientificName, nomenclaturalCode, rank);
787
		if(nonViralName.hasProblem()){
788
			for(ParserProblem p:nonViralName.getParsingProblems()){
789
				logger.warn(++parsingProblemCounter + " " +nonViralName.getTitleCache() +" "+p.toString());
790
			}
791
		}
792
		//check for parsed rank
793
		Rank parsedRank = nonViralName.getRank();
794
		if(parsedRank != rank){
795
			nonViralName.setRank(rank);
796
		}
797
		//check for parsed author
798
		String parsedAuthor = nonViralName.getAuthorshipCache();
799
		strAuthor = StringUtils.trim(strAuthor);
800
		parsedAuthor = StringUtils.trim(parsedAuthor);
801
		if(parsedAuthor.equalsIgnoreCase(strAuthor)){
802
			logger.info("Taxon " + nonViralName.getTitleCache() +":"
803
					+"\t Author field: " + strAuthor +" and parsed AuthorshipCache: "+nonViralName.getAuthorshipCache());
804
		}
805
		taxonNameBase = nonViralName;
806
		return taxonNameBase;
807
	}
808

    
809
	/**
810
	 * This method will match the BFN XML status to a distribution status
811
	 * and map it to the german federal state area. The vocabulary needs to be
812
	 * created first by the Importer, in order to map the terms correctly. Have a look
813
	 * for further details at the file BfnXmlImportAdditionalTerms.
814
	 *
815
	 *
816
     * @param taxon, for saving the distribution and its status
817
     * @param elInfoDetail, keeps the details from the import, in this case the distribution detail
818
     * @param state, import state
819
     * @param germanState, the abbreviated label for the German state
820
     *
821
     */
822
    private void createGermanDistributionStatus(Taxon taxon, Element elInfoDetail, BfnXmlImportState state,
823
            TaxonDescription taxonDescription){
824

    
825
        String strDistributionValue = elInfoDetail.getChild(BfnXmlConstants.EL_WERT).getValue();
826
        String strGermanState = elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME);
827
        //match DistributionValue
828
        UUID matchedDistributionUUID = null;
829
        PresenceAbsenceTerm status = null;
830
        try {
831
            matchedDistributionUUID = BfnXmlTransformer.matchDistributionValue(strDistributionValue);
832
            DefinedTermBase load = getTermService().load(matchedDistributionUUID);
833
            if(load.isInstanceOf(PresenceAbsenceTerm.class)) {
834
                status = CdmBase.deproxy(load, PresenceAbsenceTerm.class);
835
            }else{
836
                logger.warn(strDistributionValue + " is not PresenceAbsence Term " + load.getTitleCache() + " " + load.getTermType().toString());
837
                return;
838
            }
839
        } catch (UnknownCdmTypeException e1) {
840
            logger.warn("could not match xml value "+ strDistributionValue +" to distribution status for "+strGermanState);
841
            e1.printStackTrace();
842
            return;
843
        }
844
        //load vocabulary and german state
845
        UUID vocabularyUUID = null;
846
        TermVocabulary vocabulary = null;
847
        UUID stateUUID = null;
848

    
849
        try {
850
            stateUUID = BfnXmlTransformer.getGermanStateUUID(strGermanState);
851
        } catch (UnknownCdmTypeException e1) {
852
            logger.warn("could not match state" + strGermanState + " to UUID");
853
            e1.printStackTrace();
854
            return;
855
        }
856
        NamedArea area = (NamedArea)getTermService().load(stateUUID);
857

    
858
//        try {
859
//            vocabularyUUID =  BfnXmlTransformer.getRedlistVocabularyUUID("Bundesländer");
860
//            vocabulary = getVocabularyService().load(vocabularyUUID);
861
//        } catch (UnknownCdmTypeException e) {
862
//            logger.warn("could not load vocabulary");
863
//            e.printStackTrace();
864
//            return;
865
//        }
866
//        NamedArea area = null;
867
//        for(Object term: vocabulary){
868
//            //TODO match german state
869
//            NamedArea narea = (NamedArea) term;
870
//            Set<Representation> representations = narea.getRepresentations();
871
//            for(Representation r:representations){
872
//                if(r.getAbbreviatedLabel().equalsIgnoreCase(strGermanState)){
873
//                    area = narea;
874
//                }
875
//            }
876
//
877
//        }
878
        //create new taxon description
879
        DescriptionElementBase descriptionElement = Distribution.NewInstance(area, status);
880
        taxonDescription.addElement(descriptionElement);
881
    }
882

    
883

    
884
    @Override
885
    public boolean doCheck(BfnXmlImportState state){
886
        boolean result = true;
887
        return result;
888
    }
889

    
890
	@Override
891
	protected boolean isIgnore(BfnXmlImportState state){
892
		return ! state.getConfig().isDoTaxonNames();
893
	}
894
}
(7-7/8)