Project

General

Profile

Download (14.1 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.NonViralName;
39
import eu.etaxonomy.cdm.model.name.Rank;
40
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
41
import eu.etaxonomy.cdm.model.reference.Reference;
42
import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
43
import eu.etaxonomy.cdm.model.taxon.Synonym;
44
import eu.etaxonomy.cdm.model.taxon.Taxon;
45
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
46

    
47

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

    
56
	private static int modCount = 30000;
57
	
58
	public TcsXmlTaxonImport(){
59
		super();
60
	}
61
	
62
	
63
	@Override
64
	public boolean doCheck(TcsXmlImportState state){
65
		boolean result = true;
66
		logger.warn("Checking for Taxa not yet implemented");
67
		//result &= checkArticlesWithoutJournal(bmiConfig);
68
		//result &= checkPartOfJournal(bmiConfig);
69
		
70
		return result;
71
	}
72
	
73
	/**
74
	 * Computes a list of all TaxonConcept ids (ref-attribute) that are related as synonyms
75
	 * @param elTaxonConceptList
76
	 * @param success
77
	 * @return
78
	 */
79
	private Set<String> makeSynonymIds(List<Element> elTaxonConceptList, ResultWrapper<Boolean> success){
80
		//TODO use XPath
81
		
82
		 Set<String> result =  new HashSet<String>();
83
		
84
		Namespace tcsNamespace;
85
		//for each taxonConcept
86
		for (Element elTaxonConcept : elTaxonConceptList){
87
			tcsNamespace = elTaxonConcept.getNamespace();
88
			
89
			String childName = "TaxonRelationships";
90
			boolean obligatory = false;
91
			Element elTaxonRelationships = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory);
92

    
93
			if (elTaxonRelationships == null){
94
				continue;
95
			}
96
			String tcsElementName = "TaxonRelationship";
97
			List<Element> elTaxonRelationshipList = elTaxonRelationships.getChildren(tcsElementName, tcsNamespace);
98
			for (Element elTaxonRelationship : elTaxonRelationshipList){
99
				
100
				String relationshipType = elTaxonRelationship.getAttributeValue("type");
101
				if ("has synonym".equalsIgnoreCase(relationshipType)){
102
					childName = "ToTaxonConcept";
103
					obligatory = true;
104
					Element elToTaxonConcept = XmlHelp.getSingleChildElement(success, elTaxonRelationship, childName, tcsNamespace, obligatory);
105
					
106
					String linkType = elToTaxonConcept.getAttributeValue("linkType");
107
					if (linkType == null || linkType.equals("local")){
108
						String ref = elToTaxonConcept.getAttributeValue("ref");
109
						result.add(ref);
110
					}else{
111
						logger.warn("External link types for synonym not yet implemented");
112
					}		
113
				}
114
			}
115
		}
116
		return result;
117
	}
118
	
119
	
120
	protected static final Reference unknownSec(){
121
		ReferenceFactory refFactory = ReferenceFactory.newInstance();
122
		Reference result = refFactory.newGeneric();
123
		result.setTitleCache("UNKNOWN", true);
124
		return result;
125
	}
126
	
127
	@Override
128
	public void doInvoke(TcsXmlImportState state){
129
		
130
		logger.info("start make TaxonConcepts ...");
131
		MapWrapper<TaxonBase> taxonMap = (MapWrapper<TaxonBase>)state.getStore(ICdmIO.TAXON_STORE);
132
		MapWrapper<TaxonNameBase<?,?>> taxonNameMap = (MapWrapper<TaxonNameBase<?,?>>)state.getStore(ICdmIO.TAXONNAME_STORE);
133
		MapWrapper<Reference> referenceMap = (MapWrapper<Reference>)state.getStore(ICdmIO.REFERENCE_STORE);
134
		Map<String, CommonTaxonName> commonNameMap = new HashMap<String, CommonTaxonName>();
135
		
136
		ITaxonService taxonService = getTaxonService();
137

    
138
		ResultWrapper<Boolean> success = ResultWrapper.NewInstance(true);
139
		String childName;
140
		boolean obligatory;
141
		String idNamespace = "TaxonConcept";
142

    
143
		TcsXmlImportConfigurator config = state.getConfig();
144
		Element elDataSet = getDataSetElement(config);
145
		Namespace tcsNamespace = config.getTcsXmlNamespace();
146
		
147
		childName = "TaxonConcepts";
148
		obligatory = false;
149
		Element elTaxonConcepts = XmlHelp.getSingleChildElement(success, elDataSet, childName, tcsNamespace, obligatory);
150
		
151
		String tcsElementName = "TaxonConcept";
152
		List<Element> elTaxonConceptList = elTaxonConcepts.getChildren(tcsElementName, tcsNamespace);
153
		
154
		Set<String> synonymIdSet = makeSynonymIds(elTaxonConceptList, success);
155
		//TODO make the same for the Assertions
156
		
157
		int i = 0;
158
		
159
		//for each taxonConcept
160
		for (Element elTaxonConcept : elTaxonConceptList){
161
			if ((i++ % modCount) == 0 && i > 1){ logger.info("Taxa handled: " + (i-1));}
162
			List<String> elementList = new ArrayList<String>();
163
			
164
			//create TaxonName element
165
			String strId = elTaxonConcept.getAttributeValue("id");
166
			//TODO
167
			String strConceptType = elTaxonConcept.getAttributeValue("type"); //original, revision, incomplete, aggregate, nominal
168
			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.
169
			String strForm = elTaxonConcept.getAttributeValue("form");  //anamorph, teleomorph, hybrid
170
			
171
			childName = "Name";
172
			obligatory = true;
173
			Element elName = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory);
174
			if (isVernacular(success, elName)){
175
				handleVernacularName(success, strId, elName, commonNameMap);
176
			}else{
177
				TaxonNameBase<?,?> taxonName = makeScientificName(elName, null, taxonNameMap, success);
178
				elementList.add(childName.toString());
179
				
180
				//TODO how to handle
181
				childName = "Rank";
182
				obligatory = false;
183
				Element elRank = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory);
184
				Rank rank = TcsXmlTaxonNameImport.makeRank(elRank);
185
				if (rank != null){
186
					logger.warn("Rank in TaxonIO not yet implemented");
187
				}
188
				elementList.add(childName.toString());
189
				
190
				childName = "AccordingTo";
191
				obligatory = false;
192
				Element elAccordingTo = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory);
193
				Reference sec = makeAccordingTo(elAccordingTo, referenceMap, success);
194
				elementList.add(childName.toString());
195
				// TODO may sec be null?
196
				if (sec == null){
197
					sec = unknownSec();
198
				}
199
				
200
				TaxonBase taxonBase;
201
				if (synonymIdSet.contains(strId)){
202
					taxonBase = Synonym.NewInstance(taxonName, sec);
203
				}else{
204
					taxonBase = Taxon.NewInstance(taxonName, sec);	
205
				}
206
				
207
				childName = "TaxonRelationships";
208
				obligatory = false;
209
				Element elTaxonRelationships = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory);
210
				makeTaxonRelationships(taxonBase, elTaxonRelationships, success);
211
				elementList.add(childName.toString());
212
	
213
				childName = "SpecimenCircumscription";
214
				obligatory = false;
215
				Element elSpecimenCircumscription = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory);
216
				makeSpecimenCircumscription(taxonBase, elSpecimenCircumscription, success);
217
				elementList.add(childName.toString());
218
	
219
				childName = "CharacterCircumscription";
220
				obligatory = false;
221
				Element elCharacterCircumscription = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory);
222
				makeCharacterCircumscription(taxonBase, elCharacterCircumscription, success);
223
				elementList.add(childName.toString());
224
	
225
				
226
				childName = "ProviderLink";
227
				obligatory = false;
228
				Element elProviderLink = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory);
229
				makeProviderLink(taxonBase, elProviderLink, success);
230
				elementList.add(childName.toString());
231
				
232
				childName = "ProviderSpecificData";
233
				obligatory = false;
234
				Element elProviderSpecificData = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory);
235
				makeProviderSpecificData(taxonBase, elProviderSpecificData, success);
236
				elementList.add(childName.toString());
237
	
238
				testAdditionalElements(elTaxonConcept, elementList);
239
				ImportHelper.setOriginalSource(taxonBase, config.getSourceReference(), strId, idNamespace);
240
				taxonMap.put(strId, taxonBase);
241
			}
242
			
243
		}
244
		state.setCommonNameMap(commonNameMap);
245
		
246
		//invokeRelations(source, cdmApp, deleteAll, taxonMap, referenceMap);
247
		logger.info(i + " taxa handled. Saving ...");
248
		taxonService.save(taxonMap.objects());
249
		logger.info("end makeTaxa ...");
250
		if (!success.getValue()){
251
			state.setUnsuccessfull();
252
		}
253
		return;
254
	}
255
	
256
	private void handleVernacularName(ResultWrapper<Boolean> success, String taxonId, Element elName, Map<String, CommonTaxonName> commonNameMap) {
257
		String name = elName.getTextNormalize();
258
		//TODO ref
259
		
260
		Language language = null;
261
		String strLanguage = elName.getAttributeValue("language");
262
		//TODO
263
		//Language
264
		if (strLanguage != null){
265
			language = Language.getLanguageByLabel(strLanguage);
266
			if (language == null){
267
				language = Language.getLanguageByDescription(strLanguage);
268
			}
269
			if (language == null){
270
				logger.warn("language ("+strLanguage+") not found for name " + name);	
271
			}
272
		}
273
		CommonTaxonName commonName = CommonTaxonName.NewInstance(name, language);
274
		commonNameMap.put(taxonId, commonName);
275
		
276
		//TODO check other elements
277
	}
278

    
279

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

    
292

    
293
	
294
	private boolean hasIsSynonymRelation(Element taxonConcept, Namespace rdfNamespace){
295
		boolean result = false;
296
		if (taxonConcept == null || ! "TaxonConcept".equalsIgnoreCase(taxonConcept.getName()) ){
297
			return false;
298
		}
299
		
300
		String elName = "relationshipCategory";
301
		Filter filter = new ElementFilter(elName, taxonConcept.getNamespace());
302
		Iterator<Element> relationshipCategories = taxonConcept.getDescendants(filter);
303
		while (relationshipCategories.hasNext()){
304
			Element relationshipCategory = relationshipCategories.next();
305
			Attribute resource = relationshipCategory.getAttribute("resource", rdfNamespace);
306
			String isSynonymFor = "http://rs.tdwg.org/ontology/voc/TaxonConcept#IsSynonymFor";
307
			if (resource != null && isSynonymFor.equalsIgnoreCase(resource.getValue()) ){
308
				return true;
309
			}
310
		}
311
		return result;
312
	}
313
	
314
	
315
	/**
316
	 * @param elTaxonRelationships
317
	 * @param success
318
	 */
319
	private TaxonNameBase<?, ?> makeScientificName(Element elName, NomenclaturalCode code, MapWrapper<? extends TaxonNameBase<?,?>> objectMap, ResultWrapper<Boolean> success){
320
		TaxonNameBase<?, ?> result = null;
321
		if (elName != null){
322
			String language = elName.getAttributeValue("language");
323
			//Language
324
			if (language != null){
325
				logger.warn("language for name not yet implemented. Language for scientific name should always be Latin");	
326
			}
327
			Class<? extends IdentifiableEntity> clazz = (Class<? extends IdentifiableEntity>)NonViralName.class;
328
			if (code != null){
329
				clazz = code.getCdmClass();
330
			}
331
			result = (TaxonNameBase<?,?>)makeReferenceType (elName, clazz , objectMap, success);
332
			if(result == null){
333
				logger.warn("Name not found");
334
				success.setValue(false);
335
			}
336
		}else{
337
			logger.warn("Name element is null");
338
		}
339
		return result;
340
	}
341
	
342
	
343
	/**
344
	 * @param elTaxonRelationships
345
	 * @param success
346
	 */
347
	private void makeTaxonRelationships(TaxonBase name, Element elTaxonRelationships, ResultWrapper<Boolean> success){
348
		//TaxonRelationships are handled in TcsXmlTaxonRelationsImport
349
		return;
350
	}
351
	
352

    
353
	
354
	private void makeSpecimenCircumscription(TaxonBase name, Element elSpecimenCircumscription, ResultWrapper<Boolean> success){
355
		if (elSpecimenCircumscription != null){
356
			logger.warn("makeProviderLink not yet implemented");
357
			success.setValue(false);
358
		}
359
	}
360
	
361
	
362
	private void makeCharacterCircumscription(TaxonBase name, Element elCharacterCircumscription, ResultWrapper<Boolean> success){
363
		if (elCharacterCircumscription != null){
364
			logger.warn("makeProviderLink not yet implemented");
365
			success.setValue(false);
366
		}
367
	}
368
	
369
	private void makeProviderLink(TaxonBase name, Element elProviderLink, ResultWrapper<Boolean> success){
370
		if (elProviderLink != null){
371
			logger.warn("makeProviderLink not yet implemented");
372
			success.setValue(false);
373
		}
374
	}
375
	
376

    
377
	private void makeProviderSpecificData(TaxonBase name, Element elProviderSpecificData, ResultWrapper<Boolean> success){
378
		if (elProviderSpecificData != null){
379
			logger.warn("makeProviderLink not yet implemented");
380
			success.setValue(false);
381
		}
382
	}
383
	
384
	
385
	
386
	/* (non-Javadoc)
387
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IImportConfigurator)
388
	 */
389
	protected boolean isIgnore(TcsXmlImportState state){
390
		return ! state.getConfig().isDoTaxa();
391
	}
392

    
393

    
394
}
(8-8/11)