Project

General

Profile

« Previous | Next » 

Revision 006a8952

Added by Andreas Müller almost 9 years ago

latest changes to BfN Import

View differences:

app-import/src/main/java/eu/etaxonomy/cdm/io/redlist/bfnXml/BfnXmlImportTaxonName.java
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.taxon.Classification;
51
import eu.etaxonomy.cdm.model.taxon.Synonym;
52
import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
53
import eu.etaxonomy.cdm.model.taxon.Taxon;
54
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
55
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
56
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
57
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
58
import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
59
import eu.etaxonomy.cdm.strategy.parser.ParserProblem;
60
/**
61
 *
62
 * @author a.oppermann
63
 * @date 04.07.2013
64
 *
65
 */
66
//@Component("bfnXmlTaxonNameIO")
67
@Component
68
public class BfnXmlImportTaxonName extends BfnXmlImportBase {
69

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

  
72
	private static String strNomenclaturalCode = null;// "Zoological";//"Botanical";
73
	private static int parsingProblemCounter = 0;
74
	private Map<Integer, Taxon> firstList;
75
	private Map<Integer, Taxon> secondList;
76

  
77

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

  
82

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

  
88
		BfnXmlImportConfigurator config = state.getConfig();
89
		strNomenclaturalCode = config.getNomenclaturalSig();
90
		Element elDataSet = getDataSetElement(config);
91
		//TODO set Namespace
92
		Namespace bfnNamespace = config.getBfnXmlNamespace();
93

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  
271

  
272

  
273

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

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

  
324

  
325

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

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

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

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

  
383
					//TODO  extract to method?
384
					if(strSupplement != null){
385
						nameBase.setAppendedPhrase(strSupplement);
386
					}
387
					if(strSupplement != null && strSupplement.equalsIgnoreCase("nom. illeg.")){
388
						nameBase.addStatus(NomenclaturalStatus.NewInstance(NomenclaturalStatusType.ILLEGITIMATE()));
389
					}
390
					/**
391
					 *  BFN does not want any name matching yet
392
					 */
393
//					TaxonBase<?> taxonBase = null;
394
//					//TODO find best matching Taxa
395
//					Pager<TaxonNameBase> names = getNameService().findByTitle(null, nameBase.getTitleCache(), null, null, null, null, null, null);
396
//					//TODO  correct handling for pager
397
//					List<TaxonNameBase> nameList = names.getRecords();
398
//					if (nameList.isEmpty()){
399
//						taxonBase = Taxon.NewInstance(nameBase, config.getSourceReference());
400
//					}else{
401
//						taxonBase = Taxon.NewInstance(nameList.get(0), config.getSourceReference());
402
//						if (nameList.size()>1){
403
//							logger.warn("More than 1 matching taxon name found for " + nameBase.getTitleCache());
404
//						}
405
//					}
406
					state.setCurrentMicroRef(state.getFirstListSecRef());
407
					if(config.isFillSecondList()){
408
						state.setCurrentMicroRef(state.getSecondListSecRef());
409
					}
410
					taxon = Taxon.NewInstance(nameBase, state.getCurrentMicroRef());
411
					//set create and set path of nameSpace
412
					Element parentElement = elWissName.getParentElement();
413
					Element grandParentElement = parentElement.getParentElement();
414
					taxon.addImportSource(uniqueID, grandParentElement.getName()+":"+parentElement.getName()+":"+elWissName.getName()+":"+uriNameSpace, state.getCompleteSourceRef(), state.getCurrentMicroRef().getTitle());
415
				} catch (UnknownCdmTypeException e) {
416
					success.setValue(false);
417
				}
418
			}
419
		}
420
		return taxon;
421
	}
422

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

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

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

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

  
453
			childElementName = "NANTEIL";
454
			List<Element> elSynDetails = elSynScientificName.getChildren(childElementName, bfnNamespace);
455

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

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

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

  
480
				}
481

  
482
			}
483
		}
484
	}
485

  
486

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

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

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

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

  
510
	}
511

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

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

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

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

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

  
663

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

  
672

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

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

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

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

  
774
		NomenclaturalCode nomCode = BfnXmlTransformer.nomCodeString2NomCode(strNomenclaturalCode);
775
		String strScientificName = elWissName.getTextNormalize();
776
		/**
777
		 *
778
		 * trim strScienctificName because sometimes
779
		 * getTextNormalize() does not removes all the
780
		 * whitespaces
781
		 *
782
		 **/
783
		strScientificName = StringUtils.trim(strScientificName);
784
		strScientificName = StringUtils.remove(strScientificName, "\u00a0");
785
		strScientificName = StringUtils.remove(strScientificName, "\uc281");
786

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

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

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

  
855
        try {
856
            stateUUID = BfnXmlTransformer.getGermanStateUUID(strGermanState);
857
        } catch (UnknownCdmTypeException e1) {
858
            logger.warn("could not match state" + strGermanState + " to UUID");
859
            e1.printStackTrace();
860
            return;
861
        }
862
        NamedArea area = (NamedArea)getTermService().load(stateUUID);
863

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

  
889

  
890
    @Override
891
    public boolean doCheck(BfnXmlImportState state){
892
        boolean result = true;
893
        return result;
894
    }
895

  
896
	@Override
897
	protected boolean isIgnore(BfnXmlImportState state){
898
		return ! state.getConfig().isDoTaxonNames();
899
	}
900
}
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
					}
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff