Project

General

Profile

Download (13.8 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2009 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.tcsxml.in;
11

    
12
import java.util.ArrayList;
13
import java.util.HashMap;
14
import java.util.HashSet;
15
import java.util.Iterator;
16
import java.util.List;
17
import java.util.Map;
18
import java.util.Set;
19

    
20
import org.apache.log4j.Logger;
21
import org.jdom.Attribute;
22
import org.jdom.Element;
23
import org.jdom.Namespace;
24
import org.jdom.filter.ElementFilter;
25
import org.jdom.filter.Filter;
26
import org.springframework.stereotype.Component;
27

    
28
import eu.etaxonomy.cdm.api.service.ITaxonService;
29
import eu.etaxonomy.cdm.common.ResultWrapper;
30
import eu.etaxonomy.cdm.common.XmlHelp;
31
import eu.etaxonomy.cdm.io.common.ICdmIO;
32
import eu.etaxonomy.cdm.io.common.ImportHelper;
33
import eu.etaxonomy.cdm.io.common.MapWrapper;
34
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
35
import eu.etaxonomy.cdm.model.common.Language;
36
import eu.etaxonomy.cdm.model.description.CommonTaxonName;
37
import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
38
import eu.etaxonomy.cdm.model.name.Rank;
39
import eu.etaxonomy.cdm.model.name.TaxonName;
40
import eu.etaxonomy.cdm.model.reference.Reference;
41
import eu.etaxonomy.cdm.model.taxon.Synonym;
42
import eu.etaxonomy.cdm.model.taxon.Taxon;
43
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
44

    
45

    
46
/**
47
 * @author a.mueller
48
 *
49
 */
50
@Component
51
public class TcsXmlTaxonImport  extends TcsXmlImportBase implements ICdmIO<TcsXmlImportState> {
52
	private static final Logger logger = Logger.getLogger(TcsXmlTaxonImport.class);
53

    
54
	private static int modCount = 30000;
55

    
56
	public TcsXmlTaxonImport(){
57
		super();
58
	}
59

    
60

    
61
	@Override
62
	public boolean doCheck(TcsXmlImportState state){
63
		boolean result = true;
64
		logger.warn("Checking for Taxa not yet implemented");
65
		//result &= checkArticlesWithoutJournal(bmiConfig);
66
		//result &= checkPartOfJournal(bmiConfig);
67

    
68
		return result;
69
	}
70

    
71
	/**
72
	 * Computes a list of all TaxonConcept ids (ref-attribute) that are related as synonyms
73
	 * @param elTaxonConceptList
74
	 * @param success
75
	 * @return
76
	 */
77
	private Set<String> makeSynonymIds(List<Element> elTaxonConceptList, ResultWrapper<Boolean> success){
78
		//TODO use XPath
79

    
80
		 Set<String> result =  new HashSet<String>();
81

    
82
		Namespace tcsNamespace;
83
		//for each taxonConcept
84
		for (Element elTaxonConcept : elTaxonConceptList){
85
			tcsNamespace = elTaxonConcept.getNamespace();
86

    
87
			String childName = "TaxonRelationships";
88
			boolean obligatory = false;
89
			Element elTaxonRelationships = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory);
90

    
91
			if (elTaxonRelationships == null){
92
				continue;
93
			}
94
			String tcsElementName = "TaxonRelationship";
95
			List<Element> elTaxonRelationshipList = elTaxonRelationships == null ? new ArrayList<Element>() : elTaxonRelationships.getChildren(tcsElementName, tcsNamespace);
96
			for (Element elTaxonRelationship : elTaxonRelationshipList){
97

    
98
				String relationshipType = elTaxonRelationship.getAttributeValue("type");
99
				if ("has synonym".equalsIgnoreCase(relationshipType)){
100
					childName = "ToTaxonConcept";
101
					obligatory = true;
102
					Element elToTaxonConcept = XmlHelp.getSingleChildElement(success, elTaxonRelationship, childName, tcsNamespace, obligatory);
103

    
104
					String linkType = elToTaxonConcept.getAttributeValue("linkType");
105
					if (linkType == null || linkType.equals("local")){
106
						String ref = elToTaxonConcept.getAttributeValue("ref");
107
						result.add(ref);
108
					}else{
109
						logger.warn("External link types for synonym not yet implemented");
110
					}
111
				}
112
			}
113
		}
114
		return result;
115
	}
116

    
117

    
118

    
119

    
120
	@Override
121
	public void doInvoke(TcsXmlImportState state){
122

    
123
		logger.info("start make TaxonConcepts ...");
124
		MapWrapper<TaxonBase> taxonMap = (MapWrapper<TaxonBase>)state.getStore(ICdmIO.TAXON_STORE);
125
		MapWrapper<TaxonName<?,?>> taxonNameMap = (MapWrapper<TaxonName<?,?>>)state.getStore(ICdmIO.TAXONNAME_STORE);
126
		MapWrapper<Reference> referenceMap = (MapWrapper<Reference>)state.getStore(ICdmIO.REFERENCE_STORE);
127
		Map<String, CommonTaxonName> commonNameMap = new HashMap<String, CommonTaxonName>();
128

    
129
		ITaxonService taxonService = getTaxonService();
130

    
131
		ResultWrapper<Boolean> success = ResultWrapper.NewInstance(true);
132
		String childName;
133
		boolean obligatory;
134
		String idNamespace = "TaxonConcept";
135

    
136
		TcsXmlImportConfigurator config = state.getConfig();
137
		Element elDataSet = getDataSetElement(config);
138
		Namespace tcsNamespace = config.getTcsXmlNamespace();
139

    
140
		childName = "TaxonConcepts";
141
		obligatory = false;
142
		Element elTaxonConcepts = XmlHelp.getSingleChildElement(success, elDataSet, childName, tcsNamespace, obligatory);
143

    
144
		String tcsElementName = "TaxonConcept";
145
		List<Element> elTaxonConceptList = elTaxonConcepts.getChildren(tcsElementName, tcsNamespace);
146

    
147
		Set<String> synonymIdSet = makeSynonymIds(elTaxonConceptList, success);
148
		//TODO make the same for the Assertions
149

    
150
		int i = 0;
151

    
152
		//for each taxonConcept
153
		for (Element elTaxonConcept : elTaxonConceptList){
154
			if ((i++ % modCount) == 0 && i > 1){ logger.info("Taxa handled: " + (i-1));}
155
			List<String> elementList = new ArrayList<>();
156

    
157
			//create TaxonName element
158
			String strId = elTaxonConcept.getAttributeValue("id");
159
			//TODO
160
			String strConceptType = elTaxonConcept.getAttributeValue("type"); //original, revision, incomplete, aggregate, nominal
161
			String strPrimary = elTaxonConcept.getAttributeValue("primary"); //If primary='true' the concept is the first level response to a query. If 'false' the concept may be a secondary concept linked directly or indirectly to the definition of a primary concept.
162
			String strForm = elTaxonConcept.getAttributeValue("form");  //anamorph, teleomorph, hybrid
163

    
164
			childName = "Name";
165
			obligatory = true;
166
			Element elName = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory);
167
			if (isVernacular(success, elName)){
168
				handleVernacularName(success, strId, elName, commonNameMap);
169
			}else{
170
				TaxonName taxonName = makeScientificName(elName, null, taxonNameMap, success);
171
				elementList.add(childName.toString());
172

    
173
				//TODO how to handle
174
				childName = "Rank";
175
				obligatory = false;
176
				Element elRank = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory);
177
				Rank rank = TcsXmlTaxonNameImport.makeRank(elRank);
178
				if (rank != null){
179
					logger.warn("Rank in TaxonIO not yet implemented");
180
				}
181
				elementList.add(childName.toString());
182

    
183
				childName = "AccordingTo";
184
				obligatory = false;
185
				Element elAccordingTo = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory);
186
				Reference sec = makeAccordingTo(elAccordingTo, referenceMap, success);
187
				elementList.add(childName.toString());
188
				// TODO may sec be null?
189
				if (sec == null){
190
					sec = unknownSec();
191
				}
192

    
193
				TaxonBase<?> taxonBase;
194
				if (synonymIdSet.contains(strId)){
195
					taxonBase = Synonym.NewInstance(taxonName, sec);
196
				}else{
197
					taxonBase = Taxon.NewInstance(taxonName, sec);
198
				}
199

    
200
				childName = "TaxonRelationships";
201
				obligatory = false;
202
				Element elTaxonRelationships = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory);
203
				makeTaxonRelationships(taxonBase, elTaxonRelationships, success);
204
				elementList.add(childName.toString());
205

    
206
				childName = "SpecimenCircumscription";
207
				obligatory = false;
208
				Element elSpecimenCircumscription = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory);
209
				makeSpecimenCircumscription(taxonBase, elSpecimenCircumscription, success);
210
				elementList.add(childName.toString());
211

    
212
				childName = "CharacterCircumscription";
213
				obligatory = false;
214
				Element elCharacterCircumscription = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory);
215
				makeCharacterCircumscription(taxonBase, elCharacterCircumscription, success);
216
				elementList.add(childName.toString());
217

    
218

    
219
				childName = "ProviderLink";
220
				obligatory = false;
221
				Element elProviderLink = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory);
222
				makeProviderLink(taxonBase, elProviderLink, success);
223
				elementList.add(childName.toString());
224

    
225
				childName = "ProviderSpecificData";
226
				obligatory = false;
227
				Element elProviderSpecificData = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory);
228
				makeProviderSpecificData(taxonBase, elProviderSpecificData, success);
229
				elementList.add(childName.toString());
230

    
231
				testAdditionalElements(elTaxonConcept, elementList);
232
				ImportHelper.setOriginalSource(taxonBase, config.getSourceReference(), strId, idNamespace);
233
				//delete the version information
234

    
235
				taxonMap.put(removeVersionOfRef(strId), taxonBase);
236
			}
237

    
238
		}
239
		state.setCommonNameMap(commonNameMap);
240

    
241
		//invokeRelations(source, cdmApp, deleteAll, taxonMap, referenceMap);
242
		logger.info(i + " taxa handled. Saving ...");
243
		taxonService.save(taxonMap.objects());
244
		logger.info("end makeTaxa ...");
245
		if (!success.getValue()){
246
			state.setUnsuccessfull();
247
		}
248
		return;
249
	}
250

    
251
	private void handleVernacularName(ResultWrapper<Boolean> success, String taxonId, Element elName, Map<String, CommonTaxonName> commonNameMap) {
252
		String name = elName.getTextNormalize();
253
		//TODO ref
254

    
255
		Language language = null;
256
		String strLanguage = elName.getAttributeValue("language");
257
		//TODO
258
		//Language
259
		if (strLanguage != null){
260
			language = Language.getLanguageByLabel(strLanguage);
261
			if (language == null){
262
				language = Language.getLanguageByDescription(strLanguage);
263
			}
264
			if (language == null){
265
				logger.warn("language ("+strLanguage+") not found for name " + name);
266
			}
267
		}
268
		CommonTaxonName commonName = CommonTaxonName.NewInstance(name, language);
269
		commonNameMap.put(taxonId, commonName);
270

    
271
		//TODO check other elements
272
	}
273

    
274

    
275
	private boolean isVernacular(ResultWrapper<Boolean> success, Element elName) {
276
		try{
277
			String strScientific = elName.getAttributeValue("scientific");
278
			boolean scientific = Boolean.valueOf(strScientific);
279
			return ! scientific;
280
		} catch (Exception e) {
281
			logger.warn("Value for scientific is not boolean");
282
			success.setValue(false);
283
			return false;
284
		}
285
	}
286

    
287

    
288

    
289
	private boolean hasIsSynonymRelation(Element taxonConcept, Namespace rdfNamespace){
290
		boolean result = false;
291
		if (taxonConcept == null || ! "TaxonConcept".equalsIgnoreCase(taxonConcept.getName()) ){
292
			return false;
293
		}
294

    
295
		String elName = "relationshipCategory";
296
		Filter filter = new ElementFilter(elName, taxonConcept.getNamespace());
297
		Iterator<Element> relationshipCategories = taxonConcept.getDescendants(filter);
298
		while (relationshipCategories.hasNext()){
299
			Element relationshipCategory = relationshipCategories.next();
300
			Attribute resource = relationshipCategory.getAttribute("resource", rdfNamespace);
301
			String isSynonymFor = "http://rs.tdwg.org/ontology/voc/TaxonConcept#IsSynonymFor";
302
			if (resource != null && isSynonymFor.equalsIgnoreCase(resource.getValue()) ){
303
				return true;
304
			}
305
		}
306
		return result;
307
	}
308

    
309

    
310
	/**
311
	 * @param elTaxonRelationships
312
	 * @param success
313
	 */
314
	private TaxonName<?, ?> makeScientificName(Element elName, NomenclaturalCode code, MapWrapper<? extends TaxonName<?,?>> objectMap, ResultWrapper<Boolean> success){
315
		TaxonName<?,?> result = null;
316
		if (elName != null){
317
			String language = elName.getAttributeValue("language");
318
			//Language
319
			if (language != null){
320
				logger.warn("language for name not yet implemented. Language for scientific name should always be Latin");
321
			}
322
			Class<? extends IdentifiableEntity> clazz = TaxonName.class;
323
			result = (TaxonName<?,?>)makeReferenceType (elName, clazz , objectMap, success);
324
			if(result == null){
325
				logger.warn("Name not found");
326
				success.setValue(false);
327
			}else{
328
			    if (result.getNameType() == null){
329
			        if (code == null){
330
			            code = NomenclaturalCode.NonViral;
331
			        }
332
			        result.setNameType(code);
333
			    }
334
			}
335
		}else{
336
			logger.warn("Name element is null");
337
		}
338
		return result;
339
	}
340

    
341

    
342
	/**
343
	 * @param elTaxonRelationships
344
	 * @param success
345
	 */
346
	private void makeTaxonRelationships(TaxonBase<?> name, Element elTaxonRelationships, ResultWrapper<Boolean> success){
347
		//TaxonRelationships are handled in TcsXmlTaxonRelationsImport
348
		return;
349
	}
350

    
351

    
352

    
353
	private void makeSpecimenCircumscription(TaxonBase<?> name, Element elSpecimenCircumscription, ResultWrapper<Boolean> success){
354
		if (elSpecimenCircumscription != null){
355
			logger.warn("makeProviderLink not yet implemented");
356
			success.setValue(false);
357
		}
358
	}
359

    
360

    
361
	private void makeCharacterCircumscription(TaxonBase<?> name, Element elCharacterCircumscription, ResultWrapper<Boolean> success){
362
		if (elCharacterCircumscription != null){
363
			logger.warn("makeProviderLink not yet implemented");
364
			success.setValue(false);
365
		}
366
	}
367

    
368
	private void makeProviderLink(TaxonBase<?> name, Element elProviderLink, ResultWrapper<Boolean> success){
369
		if (elProviderLink != null){
370
			logger.warn("makeProviderLink not yet implemented");
371
			success.setValue(false);
372
		}
373
	}
374

    
375

    
376
	private void makeProviderSpecificData(TaxonBase<?> name, Element elProviderSpecificData, ResultWrapper<Boolean> success){
377
		if (elProviderSpecificData != null){
378
			logger.warn("makeProviderLink not yet implemented");
379
			success.setValue(false);
380
		}
381
	}
382

    
383

    
384

    
385
	/* (non-Javadoc)
386
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IImportConfigurator)
387
	 */
388
	@Override
389
    protected boolean isIgnore(TcsXmlImportState state){
390
		return ! state.getConfig().isDoTaxa();
391
	}
392

    
393

    
394
}
(8-8/11)