Project

General

Profile

Download (36.7 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.Rank;
49
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
50
import eu.etaxonomy.cdm.model.reference.Reference;
51
import eu.etaxonomy.cdm.model.taxon.Classification;
52
import eu.etaxonomy.cdm.model.taxon.Synonym;
53
import eu.etaxonomy.cdm.model.taxon.SynonymType;
54
import eu.etaxonomy.cdm.model.taxon.Taxon;
55
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
56
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
57
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
58
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
59
import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
60
import eu.etaxonomy.cdm.strategy.parser.ParserProblem;
61
/**
62
 *
63
 * @author a.oppermann
64
 * @date 04.07.2013
65
 *
66
 */
67
//@Component("bfnXmlTaxonNameIO")
68
@Component
69
public class BfnXmlImportTaxonName extends BfnXmlImportBase {
70

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

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

    
78

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

    
83

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

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

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

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

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

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

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

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

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

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

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

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

    
218
		//for each taxonName
219
		for (Element elTaxon : elTaxonList){
220
			//create Taxon
221
			String taxonId = elTaxon.getAttributeValue(BfnXmlConstants.ATT_TAXNR);
222
			String reihenfolge = elTaxon.getAttributeValue(BfnXmlConstants.ATT_REIHENFOLGE);
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, reihenfolge, 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 reihenfolge
326
	 * @param config
327
	 * @param bfnNamespace
328
	 * @param elTaxonName
329
	 * @param childElementName
330
	 * @param state
331
	 * @return
332
	 */
333

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

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

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

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

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

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

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

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

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

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

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

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

    
470
						//TODO find best matching Taxa
471
						Synonym synonym = Synonym.NewInstance(nameBase, state.getCurrentMicroRef());
472
						taxon.addSynonym(synonym, SynonymType.SYNONYM_OF());
473

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

    
479
				}
480

    
481
			}
482
		}
483
	}
484

    
485

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

    
498
		List<Element> elVernacularNameList = elVernacularName.getChildren(childElementName, bfnNamespace);
499

    
500
		TaxonDescription taxonDescription = getTaxonDescription(taxon, false, true);
501

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

    
509
	}
510

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

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

    
527
		List<Element> elInformationList = elInformations.getChildren(childElementName, bfnNamespace);
528

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

    
547
				for(Element elInfoDetail : elInfoDetailList){
548
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase(BfnXmlConstants.VOC_RL_KAT)){
549
						makeFeatures(taxonDescription, elInfoDetail, state, false);
550
					}
551
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase(BfnXmlConstants.VOC_KAT)){
552
						makeFeatures(taxonDescription, elInfoDetail, state, false);
553
					}
554
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase(BfnXmlConstants.VOC_AKTUELLE_BESTANDSSTITUATION)){
555
						makeFeatures(taxonDescription, elInfoDetail, state, false);
556
					}
557
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase(BfnXmlConstants.VOC_LANGFRISTIGER_BESTANDSTREND)){
558
						makeFeatures(taxonDescription, elInfoDetail, state, false);
559
					}
560
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase(BfnXmlConstants.VOC_KURZFRISTIGER_BESTANDSTREND)){
561
						makeFeatures(taxonDescription, elInfoDetail, state, false);
562
					}
563
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase(BfnXmlConstants.VOC_RISIKOFAKTOREN)){
564
						makeFeatures(taxonDescription, elInfoDetail, state, false);
565
					}
566
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase(BfnXmlConstants.VOC_VERANTWORTLICHKEIT)){
567
						makeFeatures(taxonDescription, elInfoDetail, state, false);
568
					}
569
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase(BfnXmlConstants.VOC_ALTE_RL_KAT)){
570
						makeFeatures(taxonDescription, elInfoDetail, state, false);
571
					}
572
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase(BfnXmlConstants.VOC_NEOBIOTA)){
573
						makeFeatures(taxonDescription, elInfoDetail, state, false);
574
					}
575
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase(BfnXmlConstants.VOC_EINDEUTIGER_CODE)){
576
						makeFeatures(taxonDescription, elInfoDetail, state, false);
577
					}
578
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase(BfnXmlConstants.FEAT_KOMMENTAR_TAXONOMIE)){
579
						makeFeatures(taxonDescription, elInfoDetail, state, true);
580
					}
581
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase(BfnXmlConstants.FEAT_KOMMENTAR_GEFAEHRDUNG)){
582
						makeFeatures(taxonDescription, elInfoDetail, state, true);
583
					}
584
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase(BfnXmlConstants.VOC_SONDERFAELLE)){
585
						makeFeatures(taxonDescription, elInfoDetail, state, false);
586
					}
587
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase(BfnXmlConstants.FEAT_LETZTER_NACHWEIS)){
588
						makeFeatures(taxonDescription, elInfoDetail, state, true);
589
					}
590
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase(BfnXmlConstants.FEAT_WEITERE_KOMMENTARE)){
591
						makeFeatures(taxonDescription, elInfoDetail, state, true);
592
					}
593
					//create german federal states distribution status
594
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("BW")){
595
                        createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
596
                    }
597
					//create german federal states distribution status
598
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("BY")){
599
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
600
					}
601
					//create german federal states distribution status
602
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("BE")){
603
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
604
					}
605
					//create german federal states distribution status
606
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("BB")){
607
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
608
					}
609
					//create german federal states distribution status
610
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("HB")){
611
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
612
					}
613
					//create german federal states distribution status
614
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("HH")){
615
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
616
					}
617
					//create german federal states distribution status
618
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("HE")){
619
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
620
					}
621
					//create german federal states distribution status
622
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("MV")){
623
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
624
					}
625
					//create german federal states distribution status
626
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("NI")){
627
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
628
					}
629
					//create german federal states distribution status
630
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("NW")){
631
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
632
					}
633
					//create german federal states distribution status
634
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("RP")){
635
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
636
					}
637
					//create german federal states distribution status
638
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("SL")){
639
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
640
					}
641
					//create german federal states distribution status
642
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("SN")){
643
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
644
					}
645
					//create german federal states distribution status
646
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("ST")){
647
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
648
					}
649
					//create german federal states distribution status
650
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("SH")){
651
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
652
					}
653
					//create german federal states distribution status
654
					if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("TH")){
655
					    createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
656
					}
657
				}
658
			}
659
		}
660
	}
661

    
662

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

    
671

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

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

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

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

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

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

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

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

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

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

    
884

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

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