Project

General

Profile

Download (35.4 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;
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.model.common.CdmBase;
31
import eu.etaxonomy.cdm.model.common.DefinedTermBase;
32
import eu.etaxonomy.cdm.model.common.Language;
33
import eu.etaxonomy.cdm.model.common.TermVocabulary;
34
import eu.etaxonomy.cdm.model.description.CategoricalData;
35
import eu.etaxonomy.cdm.model.description.CommonTaxonName;
36
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
37
import eu.etaxonomy.cdm.model.description.Distribution;
38
import eu.etaxonomy.cdm.model.description.Feature;
39
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
40
import eu.etaxonomy.cdm.model.description.State;
41
import eu.etaxonomy.cdm.model.description.TaxonDescription;
42
import eu.etaxonomy.cdm.model.description.TextData;
43
import eu.etaxonomy.cdm.model.location.NamedArea;
44
import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
45
import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
46
import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
47
import eu.etaxonomy.cdm.model.name.NonViralName;
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.SynonymRelationshipType;
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("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("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 = "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("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("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
				try {
162
					taxonRelationType = BfnXmlTransformer.concept2TaxonRelation(conceptStatusValue);
163
				} catch (UnknownCdmTypeException e) {
164
					e.printStackTrace();
165
				}
166
				taxon1.addTaxonRelation(taxon2, taxonRelationType , null, null);
167
			}
168
			if(taxonRelationType != null && taxonRelationType.equals(TaxonRelationshipType.ALL_RELATIONSHIPS())){
169
				List<TaxonRelationship> relationsFromThisTaxon = (List<TaxonRelationship>) taxon1.getRelationsFromThisTaxon();
170
				TaxonRelationship taxonRelationship = relationsFromThisTaxon.get(0);
171
				taxonRelationship.setDoubtful(true);
172
			}
173
			updatedTaxonList.add(taxon2);
174
			updatedTaxonList.add(taxon1);
175
		}
176
		getTaxonService().saveOrUpdate(updatedTaxonList);
177
		logger.info("taxon relationships imported...");
178
	}
179

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

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

    
215
		childName = "TAXONYME";
216
		obligatory = false;
217
		Element elTaxonNames = XmlHelp.getSingleChildElement(success, elDataSet, childName, bfnNamespace, obligatory);
218

    
219
		String bfnElementName = "TAXONYM";
220
		List<Element> elTaxonList = elTaxonNames.getChildren(bfnElementName, bfnNamespace);
221

    
222
		//for each taxonName
223
		for (Element elTaxon : elTaxonList){
224
			//create Taxon
225
			String taxonId = elTaxon.getAttributeValue("taxNr");
226
			childName = "WISSNAME";
227
			Element elWissName = XmlHelp.getSingleChildElement(success, elTaxon, childName, bfnNamespace, obligatory);
228
			String childElementName = "NANTEIL";
229
			Taxon taxon = createOrUpdateTaxon(success, idNamespace, config, bfnNamespace, elWissName, childElementName, state);
230

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

    
258
		//Quick'n'dirty to set concept relationships between two imported list
259
		prepareListforConceptImport(config, taxonMap);
260

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

    
272

    
273

    
274

    
275
	/**
276
	 * This will put the prior imported list into a classification
277
	 *
278
	 * @param config
279
	 * @param taxonService
280
	 * @param config
281
	 * @param savedTaxonMap
282
	 * @param currentElement
283
	 * @param state
284
	 * @return
285
	 */
286
	@SuppressWarnings("rawtypes")
287
	private boolean createOrUpdateClassification(BfnXmlImportConfigurator config, ITaxonService taxonService, Map<UUID, TaxonBase> savedTaxonMap, Element currentElement, BfnXmlImportState state) {
288
		boolean isNewClassification = true;
289
		String classificationName = state.getFirstClassificationName();
290
		if(config.isFillSecondList()){
291
			classificationName = state.getSecondClassificationName();
292
		}
293
//		if(classificationName == null){
294
//			classificationName = config.getClassificationName();
295
//		}
296
		//TODO make classification name dynamically depending on its value in the XML.
297
		Classification classification = Classification.NewInstance(classificationName+" "+currentElement.getAttributeValue("inhalt"), state.getCompleteSourceRef());
298
		//TODO do we really want toString() or titleCache here?
299
		String microRef = state.getCurrentMicroRef() == null ? null : state.getCurrentMicroRef().toString();
300
		classification.addImportSource(Integer.toString(classification.getId()), classification.getTitleCache(), state.getCompleteSourceRef(), microRef);
301
//		List<Classification> classificationList = getClassificationService().list(Classification.class, null, null, null, VOC_CLASSIFICATION_INIT_STRATEGY);
302
//		for(Classification c : classificationList){
303
//			if(c.getTitleCache().equalsIgnoreCase(classification.getTitleCache())){
304
//				classification = c;
305
//				isNewClassification = false;
306
//			}
307
//		}
308

    
309
//		ArrayList<TaxonBase> taxonBaseList = (ArrayList<TaxonBase>) taxonService.list(TaxonBase.class, null, null, null, VOC_CLASSIFICATION_INIT_STRATEGY);
310
		for(TaxonBase tb:savedTaxonMap.values()){
311
			if(tb instanceof Taxon){
312
				TaxonBase tbase = CdmBase.deproxy(tb, TaxonBase.class);
313
				Taxon taxon = (Taxon)tbase;
314
				taxon = CdmBase.deproxy(taxon, Taxon.class);
315
				classification.addChildTaxon(taxon, null, null);
316
			}
317
		}
318
		IClassificationService classificationService = getClassificationService();
319
		classificationService.saveOrUpdate(classification);
320
		//set boolean for reference and internal mapping of concept relations
321
		if(config.isHasSecondList()){
322
			config.setFillSecondList(true);
323
		}
324
		return isNewClassification;
325
	}
326

    
327

    
328

    
329
	/**
330
	 * Matches the XML attributes against CDM entities.<BR>
331
	 * Imports Scientific Name, Rank, etc. and creates a taxon.<br>
332
	 * <b>Existing taxon names won't be matched yet</b>
333
	 *
334
	 * @param success
335
	 * @param idNamespace
336
	 * @param config
337
	 * @param bfnNamespace
338
	 * @param elTaxonName
339
	 * @param childElementName
340
	 * @param state
341
	 * @return
342
	 */
343

    
344
	@SuppressWarnings({ "unchecked" })
345
	private Taxon createOrUpdateTaxon(
346
			ResultWrapper<Boolean> success, String idNamespace,
347
			BfnXmlImportConfigurator config, Namespace bfnNamespace,
348
			Element elTaxonName, String childElementName, BfnXmlImportState state) {
349

    
350
		List<Element> elWissNameList = elTaxonName.getChildren(childElementName, bfnNamespace);
351
		Rank rank = null;
352
		String strAuthor = null;
353
		String strSupplement = null;
354
		Taxon taxon = null;
355
		String uniqueID = null;
356
		String uriNameSpace = null;
357
//		Long uniqueID = null;
358
		for(Element elWissName:elWissNameList){
359

    
360
			if(elWissName.getAttributeValue("bereich", bfnNamespace).equalsIgnoreCase("Eindeutiger Code")){
361
				uriNameSpace = elWissName.getAttributeValue("bereich");
362
				String textNormalize = elWissName.getTextNormalize();
363
				if(StringUtils.isBlank(textNormalize)){
364
					uniqueID = "";
365
				}else{
366
					uniqueID = textNormalize;
367
				}
368
			}
369
			if(elWissName.getAttributeValue("bereich", bfnNamespace).equalsIgnoreCase("Autoren")){
370
				strAuthor = elWissName.getTextNormalize();
371
			}
372
			if(elWissName.getAttributeValue("bereich", bfnNamespace).equalsIgnoreCase("Rang")){
373
				String strRank = elWissName.getTextNormalize();
374
				rank = makeRank(strRank);
375
			}
376
			if(elWissName.getAttributeValue("bereich", bfnNamespace).equalsIgnoreCase("Zusätze")){
377
				strSupplement = elWissName.getTextNormalize();
378
			}
379
			if(elWissName.getAttributeValue("bereich", bfnNamespace).equalsIgnoreCase("wissName")){
380
				try{
381
					TaxonNameBase<?, ?> nameBase = parseNonviralNames(rank,strAuthor,strSupplement,elWissName);
382
					if(nameBase.isProtectedTitleCache() == true){
383
						logger.warn("Taxon " + nameBase.getTitleCache());
384
					}
385

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

    
410
					Reference<?> microRef = config.isFillSecondList() ?
411
					        state.getSecondListSecRef():
412
					        state.getFirstListSecRef();
413
					state.setCurrentMicroRef(microRef);
414
					taxon = Taxon.NewInstance(nameBase, state.getCurrentMicroRef());
415
					//set create and set path of nameSpace
416
					Element parentElement = elWissName.getParentElement();
417
					Element grandParentElement = parentElement.getParentElement();
418
					String namespace = grandParentElement.getName() + ":" + parentElement.getName() + ":"+elWissName.getName() + ":" + uriNameSpace;
419
					String microRefStr = microRef == null ? null : microRef.getTitle();
420
					taxon.addImportSource(uniqueID, namespace, state.getCompleteSourceRef(), microRefStr);
421
				} catch (UnknownCdmTypeException e) {
422
					success.setValue(false);
423
				}
424
			}
425
		}
426
		return taxon;
427
	}
428

    
429
	/**
430
	 * Matches the XML attributes against CDM entities.<BR>
431
	 * Imports Scientific Name, Rank etc. and create a synonym.<br>
432
	 * <b>Existing synonym names won't be matched yet</b>
433
	 *
434
	 * @param taxon
435
	 * @param success
436
	 * @param obligatory
437
	 * @param bfnNamespace
438
	 * @param childElementName
439
	 * @param elSynonyms
440
	 * @param taxonId
441
	 * @param config
442
	 * @param state
443
	 */
444

    
445
	@SuppressWarnings({ "unchecked" })
446
	private void createOrUpdateSynonym(Taxon taxon, ResultWrapper<Boolean> success, boolean obligatory, Namespace bfnNamespace,
447
			     String childElementName, Element elSynonyms, String taxonId, BfnXmlImportState state) {
448

    
449
		String childName;
450
		List<Element> elSynonymList = elSynonyms.getChildren(childElementName, bfnNamespace);
451

    
452
		for(Element elSyn:elSynonymList){
453
			Rank rank = null;
454
			String strAuthor = null;
455
			String strSupplement = null;
456
			childName = "WISSNAME";
457
			Element elSynScientificName = XmlHelp.getSingleChildElement(success, elSyn, childName, bfnNamespace, obligatory);
458

    
459
			childElementName = "NANTEIL";
460
			List<Element> elSynDetails = elSynScientificName.getChildren(childElementName, bfnNamespace);
461

    
462
			for(Element elSynDetail:elSynDetails){
463
				if(elSynDetail.getAttributeValue("bereich").equalsIgnoreCase("Rang")){
464
					String strRank = elSynDetail.getTextNormalize();
465
					rank = makeRank(strRank);
466
				}
467
				if(elSynDetail.getAttributeValue("bereich").equalsIgnoreCase("Autoren")){
468
					strAuthor = elSynDetail.getTextNormalize();
469
				}
470
				if(elSynDetail.getAttributeValue("bereich", bfnNamespace).equalsIgnoreCase("Zusätze")){
471
					strSupplement = elSynDetail.getTextNormalize();
472
				}
473
				if(elSynDetail.getAttributeValue("bereich").equalsIgnoreCase("wissName")){
474
					try{
475
						TaxonNameBase<?, ?> nameBase = parseNonviralNames(rank,strAuthor,strSupplement,elSynDetail);
476

    
477
						//TODO find best matching Taxa
478
						Synonym synonym = Synonym.NewInstance(nameBase, state.getCurrentMicroRef());
479
						taxon.addSynonym(synonym, SynonymRelationshipType.SYNONYM_OF());
480

    
481
					} catch (UnknownCdmTypeException e) {
482
						logger.warn("Name with id " + taxonId + " has unknown nomenclatural code.");
483
						success.setValue(false);
484
					}
485

    
486
				}
487

    
488
			}
489
		}
490
	}
491

    
492

    
493
	/**
494
	 *
495
	 * @param taxon
496
	 * @param bfnNamespace
497
	 * @param childElementName
498
	 * @param elVernacularName
499
	 * @param state
500
	 */
501
	private void createOrUpdateVernacularName(Taxon taxon,
502
			Namespace bfnNamespace, String childElementName,
503
			Element elVernacularName, BfnXmlImportState state) {
504

    
505
		List<Element> elVernacularNameList = elVernacularName.getChildren(childElementName, bfnNamespace);
506

    
507
		TaxonDescription taxonDescription = getTaxonDescription(taxon, false, true);
508

    
509
		for(Element elVernacular : elVernacularNameList){
510
			Element child = elVernacular.getChild("TRIVIALNAME");
511
			if(child != null){
512
				makeCommonName(taxonDescription, child, state);
513
			}
514
		}
515

    
516
	}
517

    
518
	/**
519
	 *
520
	 * @param taxon
521
	 * @param bfnNamespace
522
	 * @param childElementName
523
	 * @param elInformations
524
	 * @param state
525
	 * @throws UnknownCdmTypeException
526
	 */
527

    
528
	@SuppressWarnings("unchecked")
529
	private void createOrUpdateInformation(Taxon taxon,
530
			Namespace bfnNamespace, String childElementName,
531
			Element elInformations,
532
			BfnXmlImportState state){
533

    
534
		List<Element> elInformationList = elInformations.getChildren(childElementName, bfnNamespace);
535

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

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

    
669

    
670
    private void makeCommonName(TaxonDescription taxonDescription,
671
			Element child, BfnXmlImportState state) {
672
		String commonNameValue = child.getValue();
673
		NamedArea area = getTermService().getAreaByTdwgAbbreviation("GER");
674
		CommonTaxonName commonName = CommonTaxonName.NewInstance(commonNameValue, Language.GERMAN(), area);
675
		taxonDescription.addElement(commonName);
676
	}
677

    
678

    
679
	/**
680
	 *
681
	 * @param taxonDescription
682
	 * @param elInfoDetail
683
	 * @param state
684
	 * @param isTextData
685
	 */
686
	private void makeFeatures(
687
			TaxonDescription taxonDescription,
688
			Element elInfoDetail,
689
			BfnXmlImportState state,
690
			boolean isTextData) {
691

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

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

    
768
	/**
769
	 * @param rank
770
	 * @param strAuthor
771
	 * @param strSupplement
772
	 * @param elWissName
773
	 * @return
774
	 * @throws UnknownCdmTypeException
775
	 */
776
	private TaxonNameBase<?, ?> parseNonviralNames(Rank rank, String strAuthor, String strSupplement, Element elWissName)
777
			throws UnknownCdmTypeException {
778
		TaxonNameBase<?,?> taxonNameBase = null;
779

    
780
		String strScientificName = elWissName.getTextNormalize();
781
		/**
782
		 *
783
		 * trim strScienctificName because sometimes
784
		 * getTextNormalize() does not removes all the
785
		 * whitespaces
786
		 *
787
		 **/
788
		strScientificName = StringUtils.trim(strScientificName);
789
		strScientificName = StringUtils.remove(strScientificName, "\u00a0");
790
		strScientificName = StringUtils.remove(strScientificName, "\uc281");
791

    
792
		if(strSupplement != null && !strSupplement.isEmpty()){
793
			strScientificName = StringUtils.remove(strScientificName, strSupplement);
794
		}
795
		NonViralName<?> nonViralName = null;
796
		NonViralNameParserImpl parser = NonViralNameParserImpl.NewInstance();
797
		nonViralName = parser.parseFullName(strScientificName, nomenclaturalCode, rank);
798
		if(nonViralName.hasProblem()){
799
			for(ParserProblem p:nonViralName.getParsingProblems()){
800
				logger.warn(++parsingProblemCounter + " " +nonViralName.getTitleCache() +" "+p.toString());
801
			}
802
		}
803
		//check for parsed rank
804
		Rank parsedRank = nonViralName.getRank();
805
		if(parsedRank != rank){
806
			nonViralName.setRank(rank);
807
		}
808
		//check for parsed author
809
		String parsedAuthor = nonViralName.getAuthorshipCache();
810
		strAuthor = StringUtils.trim(strAuthor);
811
		parsedAuthor = StringUtils.trim(parsedAuthor);
812
		if(parsedAuthor.equalsIgnoreCase(strAuthor)){
813
			logger.info("Taxon " + nonViralName.getTitleCache() +":"
814
					+"\t Author field: " + strAuthor +" and parsed AuthorshipCache: "+nonViralName.getAuthorshipCache());
815
		}
816
		taxonNameBase = nonViralName;
817
		return taxonNameBase;
818
	}
819

    
820
	/**
821
	 * This method will match the BFN XML status to a distribution status
822
	 * and map it to the german federal state area. The vocabulary needs to be
823
	 * created first by the Importer, in order to map the terms correctly. Have a look
824
	 * for further details at the file BfnXmlImportAdditionalTerms.
825
	 *
826
	 *
827
     * @param taxon, for saving the distribution and its status
828
     * @param elInfoDetail, keeps the details from the import, in this case the distribution detail
829
     * @param state, import state
830
     * @param germanState, the abbreviated label for the German state
831
     *
832
     */
833
    private void createGermanDistributionStatus(Taxon taxon, Element elInfoDetail, BfnXmlImportState state,
834
            TaxonDescription taxonDescription){
835

    
836
        String strDistributionValue = elInfoDetail.getChild("WERT").getValue();
837
        String strGermanState = elInfoDetail.getAttributeValue("standardname");
838
        //match DistributionValue
839
        UUID matchedDistributionUUID = null;
840
        PresenceAbsenceTerm status = null;
841
        try {
842
            matchedDistributionUUID = BfnXmlTransformer.matchDistributionValue(strDistributionValue);
843
            DefinedTermBase load = getTermService().load(matchedDistributionUUID);
844
            if(load.isInstanceOf(PresenceAbsenceTerm.class)) {
845
                status = CdmBase.deproxy(load, PresenceAbsenceTerm.class);
846
            }else{
847
                logger.warn(strDistributionValue + " is not PresenceAbsence Term " + load.getTitleCache() + " " + load.getTermType().toString());
848
                return;
849
            }
850
        } catch (UnknownCdmTypeException e1) {
851
            logger.warn("could not match xml value "+ strDistributionValue +" to distribution status for "+strGermanState);
852
            e1.printStackTrace();
853
            return;
854
        }
855
        //load vocabulary and german state
856
        UUID vocabularyUUID = null;
857
        TermVocabulary vocabulary = null;
858
        UUID stateUUID = null;
859

    
860
        try {
861
            stateUUID = BfnXmlTransformer.getGermanStateUUID(strGermanState);
862
        } catch (UnknownCdmTypeException e1) {
863
            logger.warn("could not match state" + strGermanState + " to UUID");
864
            e1.printStackTrace();
865
            return;
866
        }
867
        NamedArea area = (NamedArea)getTermService().load(stateUUID);
868

    
869
//        try {
870
//            vocabularyUUID =  BfnXmlTransformer.getRedlistVocabularyUUID("Bundesländer");
871
//            vocabulary = getVocabularyService().load(vocabularyUUID);
872
//        } catch (UnknownCdmTypeException e) {
873
//            logger.warn("could not load vocabulary");
874
//            e.printStackTrace();
875
//            return;
876
//        }
877
//        NamedArea area = null;
878
//        for(Object term: vocabulary){
879
//            //TODO match german state
880
//            NamedArea narea = (NamedArea) term;
881
//            Set<Representation> representations = narea.getRepresentations();
882
//            for(Representation r:representations){
883
//                if(r.getAbbreviatedLabel().equalsIgnoreCase(strGermanState)){
884
//                    area = narea;
885
//                }
886
//            }
887
//
888
//        }
889
        //create new taxon description
890
        DescriptionElementBase descriptionElement = Distribution.NewInstance(area, status);
891
        taxonDescription.addElement(descriptionElement);
892
    }
893

    
894

    
895
    @Override
896
    public boolean doCheck(BfnXmlImportState state){
897
        boolean result = true;
898
        return result;
899
    }
900

    
901
	@Override
902
	protected boolean isIgnore(BfnXmlImportState state){
903
		return ! state.getConfig().isDoTaxonNames();
904
	}
905
}
(7-7/8)