Revision 608b3df3
Added by Andreas Müller about 2 years ago
cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/tcsxml/in/TcsXmlTaxonRelationsImport.java | ||
---|---|---|
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.io.InputStream; |
|
13 |
import java.util.ArrayList; |
|
14 |
import java.util.HashSet; |
|
15 |
import java.util.List; |
|
16 |
import java.util.Map; |
|
17 |
import java.util.Set; |
|
18 |
|
|
19 |
import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger; |
|
20 |
import org.jdom.Element; |
|
21 |
import org.jdom.Namespace; |
|
22 |
import org.springframework.beans.factory.annotation.Autowired; |
|
23 |
import org.springframework.stereotype.Component; |
|
24 |
|
|
25 |
import eu.etaxonomy.cdm.common.CdmUtils; |
|
26 |
import eu.etaxonomy.cdm.common.ResultWrapper; |
|
27 |
import eu.etaxonomy.cdm.common.XmlHelp; |
|
28 |
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper; |
|
29 |
import eu.etaxonomy.cdm.io.common.ICdmIO; |
|
30 |
import eu.etaxonomy.cdm.io.common.MapWrapper; |
|
31 |
import eu.etaxonomy.cdm.io.tcsrdf.TcsRdfImportConfigurator; |
|
32 |
import eu.etaxonomy.cdm.io.tcsrdf.TcsRdfTaxonNameImport; |
|
33 |
import eu.etaxonomy.cdm.io.tcsxml.TcsXmlTransformer; |
|
34 |
import eu.etaxonomy.cdm.model.common.CdmBase; |
|
35 |
import eu.etaxonomy.cdm.model.common.RelationshipTermBase; |
|
36 |
import eu.etaxonomy.cdm.model.description.CommonTaxonName; |
|
37 |
import eu.etaxonomy.cdm.model.description.TaxonDescription; |
|
38 |
import eu.etaxonomy.cdm.model.name.TaxonName; |
|
39 |
import eu.etaxonomy.cdm.model.name.TaxonNameFactory; |
|
40 |
import eu.etaxonomy.cdm.model.reference.OriginalSourceType; |
|
41 |
import eu.etaxonomy.cdm.model.reference.Reference; |
|
42 |
import eu.etaxonomy.cdm.model.taxon.Classification; |
|
43 |
import eu.etaxonomy.cdm.model.taxon.Synonym; |
|
44 |
import eu.etaxonomy.cdm.model.taxon.SynonymType; |
|
45 |
import eu.etaxonomy.cdm.model.taxon.Taxon; |
|
46 |
import eu.etaxonomy.cdm.model.taxon.TaxonBase; |
|
47 |
import eu.etaxonomy.cdm.model.taxon.TaxonNode; |
|
48 |
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType; |
|
49 |
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException; |
|
50 |
|
|
51 |
|
|
52 |
/** |
|
53 |
* @author a.mueller |
|
54 |
* |
|
55 |
*/ |
|
56 |
@Component |
|
57 |
public class TcsXmlTaxonRelationsImport extends TcsXmlImportBase implements ICdmIO<TcsXmlImportState> { |
|
58 |
private static final long serialVersionUID = 6632990505515905663L; |
|
59 |
|
|
60 |
private static final Logger logger = LogManager.getLogger(TcsXmlTaxonRelationsImport.class); |
|
61 |
|
|
62 |
private static int modCount = 30000; |
|
63 |
|
|
64 |
@Autowired |
|
65 |
private TcsRdfTaxonNameImport rdfNameImport; |
|
66 |
private TcsRdfImportConfigurator rdfConfig = TcsRdfImportConfigurator.NewInstance(null, null); |
|
67 |
|
|
68 |
public TcsXmlTaxonRelationsImport(){ |
|
69 |
super(); |
|
70 |
|
|
71 |
} |
|
72 |
|
|
73 |
@Override |
|
74 |
public boolean doCheck(TcsXmlImportState state){ |
|
75 |
boolean result = true; |
|
76 |
logger.warn("Checking for TaxonRelations not yet implemented"); |
|
77 |
logger.warn("Creation of homotypic relations is still problematic"); |
|
78 |
//result &= checkArticlesWithoutJournal(bmiConfig); |
|
79 |
//result &= checkPartOfJournal(bmiConfig); |
|
80 |
|
|
81 |
return result; |
|
82 |
} |
|
83 |
|
|
84 |
@Override |
|
85 |
public void doInvoke(TcsXmlImportState state){ |
|
86 |
|
|
87 |
|
|
88 |
logger.info("start make taxon relations ..."); |
|
89 |
MapWrapper<TaxonBase> taxonMap = (MapWrapper<TaxonBase>)state.getStore(ICdmIO.TAXON_STORE); |
|
90 |
MapWrapper<TaxonName> taxonNameMap = (MapWrapper<TaxonName>)state.getStore(ICdmIO.TAXONNAME_STORE); |
|
91 |
MapWrapper<Reference> referenceMap = (MapWrapper<Reference>)state.getStore(ICdmIO.REFERENCE_STORE); |
|
92 |
|
|
93 |
Set<TaxonBase> taxonStore = new HashSet<TaxonBase>(); |
|
94 |
|
|
95 |
ResultWrapper<Boolean> success = ResultWrapper.NewInstance(true); |
|
96 |
String childName; |
|
97 |
boolean obligatory; |
|
98 |
String idNamespace = "TaxonRelationDTO"; |
|
99 |
|
|
100 |
TcsXmlImportConfigurator config = state.getConfig(); |
|
101 |
Element elDataSet = super.getDataSetElement(config); |
|
102 |
Namespace tcsNamespace = config.getTcsXmlNamespace(); |
|
103 |
|
|
104 |
childName = "TaxonConcepts"; |
|
105 |
obligatory = false; |
|
106 |
Element elTaxonConcepts = XmlHelp.getSingleChildElement(success, elDataSet, childName, tcsNamespace, obligatory); |
|
107 |
|
|
108 |
childName = "TaxonConcept"; |
|
109 |
List<Element> elTaxonConceptList = elTaxonConcepts == null ? new ArrayList<Element>() : elTaxonConcepts.getChildren(childName, tcsNamespace); |
|
110 |
|
|
111 |
int i = 0; |
|
112 |
int taxonRelCount = 0; |
|
113 |
|
|
114 |
//for each taxonConcept |
|
115 |
logger.info("NUmber of taxon concepts: " + elTaxonConceptList.size()); |
|
116 |
for (Element elTaxonConcept : elTaxonConceptList){ |
|
117 |
if ((i++ % modCount) == 0){ logger.info("Taxa handled: " + (i-1));} |
|
118 |
taxonRelCount += makeTaxonConcept(state, taxonMap, taxonStore, elTaxonConcept, tcsNamespace, success); |
|
119 |
}//elTaxonConcept |
|
120 |
logger.info("Taxa handled: " + taxonStore.size()); |
|
121 |
//TaxonRelationshipAssertions |
|
122 |
taxonRelCount += makeTaxonRelationshipAssertion(state, taxonMap, referenceMap, taxonStore, elDataSet, tcsNamespace, success); |
|
123 |
|
|
124 |
logger.info("Taxa to save: " + taxonStore.size()); |
|
125 |
getTaxonService().save(taxonStore); |
|
126 |
|
|
127 |
//do basionym relationships |
|
128 |
childName = "TaxonNames"; |
|
129 |
obligatory = false; |
|
130 |
Element elTaxonNames = XmlHelp.getSingleChildElement(success, elDataSet, childName, tcsNamespace, obligatory); |
|
131 |
|
|
132 |
childName = "TaxonName"; |
|
133 |
List<Element> elTaxonNameList = elTaxonNames == null ? new ArrayList<Element>() : elTaxonNames.getChildren(childName, tcsNamespace); |
|
134 |
|
|
135 |
logger.info("NUmber of taxon concepts: " + elTaxonNameList.size()); |
|
136 |
for (Element elTaxonName : elTaxonNameList){ |
|
137 |
if ((i++ % modCount) == 0){ logger.info("Taxa handled: " + (i-1));} |
|
138 |
taxonRelCount += makeBasionymRelations(state, taxonMap, taxonNameMap, taxonStore, elTaxonName, tcsNamespace, success); |
|
139 |
}//elTaxonConcept |
|
140 |
logger.info("Taxa handled: " + taxonStore.size()); |
|
141 |
|
|
142 |
|
|
143 |
taxonStore = null; |
|
144 |
logger.info("end make taxon relations ..."); |
|
145 |
if (!success.getValue()){ |
|
146 |
state.setUnsuccessfull(); |
|
147 |
} |
|
148 |
return; |
|
149 |
} |
|
150 |
|
|
151 |
private int makeBasionymRelations(TcsXmlImportState state, |
|
152 |
MapWrapper<TaxonBase> taxonMap, MapWrapper<TaxonName> taxonNameMap, Set<TaxonBase> taxonStore, |
|
153 |
Element elTaxonName, Namespace tcsNamespace, |
|
154 |
ResultWrapper<Boolean> success) { |
|
155 |
|
|
156 |
/* |
|
157 |
* <tcs:Basionym> |
|
158 |
<tcs:RelatedName ref="urn:lsid:ipni.org:names:50000063-1">Caryophyllaceae</tcs:RelatedName> |
|
159 |
</tcs:Basionym> |
|
160 |
*/ |
|
161 |
|
|
162 |
|
|
163 |
String childName = "Basionym"; |
|
164 |
boolean obligatory = false; |
|
165 |
Element elBasionymRelationships = XmlHelp.getSingleChildElement(success, elTaxonName, childName, tcsNamespace, obligatory); |
|
166 |
if (elBasionymRelationships != null){ |
|
167 |
childName = "RelatedName"; |
|
168 |
obligatory = false; |
|
169 |
Element elBasionym = XmlHelp.getSingleChildElement(success, elBasionymRelationships, childName, tcsNamespace, obligatory); |
|
170 |
|
|
171 |
String id = elTaxonName.getAttributeValue("id"); |
|
172 |
TaxonName name = taxonNameMap.get(removeVersionOfRef(id)); |
|
173 |
|
|
174 |
TaxonBase taxonBase = (TaxonBase)name.getTaxonBases().iterator().next(); |
|
175 |
|
|
176 |
String ref = elBasionym.getAttributeValue("ref"); |
|
177 |
TaxonName basionymName = taxonNameMap.get(removeVersionOfRef(ref)); |
|
178 |
|
|
179 |
if (basionymName != null){ |
|
180 |
basionymName = HibernateProxyHelper.deproxy(basionymName, TaxonName.class); |
|
181 |
TaxonBase basionym; |
|
182 |
if (basionymName.getTaxonBases().isEmpty()){ |
|
183 |
basionym = Synonym.NewInstance(basionymName, null); |
|
184 |
}else{ |
|
185 |
basionym = (TaxonBase)basionymName.getTaxonBases().iterator().next(); |
|
186 |
} |
|
187 |
//Synonym basionymSyn; |
|
188 |
if (basionym instanceof Taxon){ |
|
189 |
|
|
190 |
if (!(taxonBase instanceof Synonym)){ |
|
191 |
logger.debug("The taxon " + basionymName.getTitleCache() + " is used in a concept and can not be a synonym " + name.getTitleCache() + "but will be added as basionym for the homotypical group"); |
|
192 |
name.addBasionym(basionymName); |
|
193 |
//basionymName.getHomotypicalGroup().addTypifiedName(name); |
|
194 |
} else if (taxonBase instanceof Synonym){ |
|
195 |
Synonym synonym = (Synonym) taxonBase; |
|
196 |
((Taxon)basionym).addSynonym(synonym, SynonymType.HOMOTYPIC_SYNONYM_OF()); |
|
197 |
basionym.getHomotypicGroup().setGroupBasionym(basionymName); |
|
198 |
taxonStore.add(basionym); |
|
199 |
} |
|
200 |
}else{ |
|
201 |
if (taxonBase instanceof Taxon){ |
|
202 |
Synonym synonym = (Synonym) basionym; |
|
203 |
((Taxon)taxonBase).addSynonym(synonym, SynonymType.HOMOTYPIC_SYNONYM_OF()); |
|
204 |
taxonBase.getHomotypicGroup().setGroupBasionym(basionymName); |
|
205 |
taxonStore.add(taxonBase); |
|
206 |
} else{ |
|
207 |
Taxon acc = ((Synonym)taxonBase).getAcceptedTaxon(); |
|
208 |
if (acc != null){ |
|
209 |
acc.addHomotypicSynonym((Synonym)basionym); |
|
210 |
basionymName.getHomotypicalGroup().setGroupBasionym(basionymName); |
|
211 |
} |
|
212 |
} |
|
213 |
} |
|
214 |
|
|
215 |
|
|
216 |
} else{ |
|
217 |
basionymName = TaxonNameFactory.NewNonViralInstance(name.getRank()); |
|
218 |
childName = "RelatedName"; |
|
219 |
obligatory = true; |
|
220 |
Element elName = XmlHelp.getSingleChildElement(success, elBasionym, childName, tcsNamespace, obligatory); |
|
221 |
String strName = (elName == null)? "" : elName.getTextNormalize(); |
|
222 |
basionymName.setTitleCache(strName, false); |
|
223 |
Synonym basionymSyn = Synonym.NewInstance(basionymName, unknownSec()); |
|
224 |
if (taxonBase instanceof Taxon){ |
|
225 |
Taxon taxon = (Taxon)taxonBase; |
|
226 |
taxon.addSynonym(basionymSyn, SynonymType.HOMOTYPIC_SYNONYM_OF()); |
|
227 |
taxon.getHomotypicGroup().setGroupBasionym(basionymName); |
|
228 |
taxonStore.add(taxon); |
|
229 |
} else{ |
|
230 |
Synonym syn = (Synonym) taxonBase; |
|
231 |
if (syn.getAcceptedTaxon() != null){ |
|
232 |
Taxon accTaxon = syn.getAcceptedTaxon(); |
|
233 |
accTaxon.addSynonym(basionymSyn, SynonymType.HOMOTYPIC_SYNONYM_OF()); |
|
234 |
accTaxon.getHomotypicGroup().setGroupBasionym(basionymName); |
|
235 |
taxonStore.add(accTaxon); |
|
236 |
} |
|
237 |
} |
|
238 |
} |
|
239 |
} |
|
240 |
return 1; |
|
241 |
} |
|
242 |
|
|
243 |
private int makeTaxonConcept(TcsXmlImportState state, MapWrapper<TaxonBase> taxonMap, Set<TaxonBase> taxonStore, Element elTaxonConcept, Namespace tcsNamespace, ResultWrapper<Boolean> success){ |
|
244 |
int taxonRelCount = 0; |
|
245 |
|
|
246 |
String childName = "TaxonRelationships"; |
|
247 |
boolean obligatory = false; |
|
248 |
Element elTaxonRelationships = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory); |
|
249 |
|
|
250 |
if (elTaxonRelationships != null){ |
|
251 |
//Relationships |
|
252 |
String tcsElementName = "TaxonRelationship"; |
|
253 |
List<Element> elTaxonRelationshipList = elTaxonRelationships.getChildren(tcsElementName, tcsNamespace); |
|
254 |
logger.info("Number of taxonrelationships: " + elTaxonRelationshipList.size()); |
|
255 |
for (Element elTaxonRelationship: elTaxonRelationshipList){ |
|
256 |
|
|
257 |
taxonRelCount++; |
|
258 |
logger.debug("TaxonRelationship "+ taxonRelCount); |
|
259 |
|
|
260 |
String strId = elTaxonConcept.getAttributeValue("id"); |
|
261 |
//TODO |
|
262 |
// String strConceptType = elTaxonConcept.getAttributeValue("type"); //original, revision, incomplete, aggregate, nominal |
|
263 |
// 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. |
|
264 |
// String strForm = elTaxonConcept.getAttributeValue("form"); //anamorph, teleomorph, hybrid |
|
265 |
|
|
266 |
TaxonBase fromTaxon = taxonMap.get(removeVersionOfRef(strId)); |
|
267 |
makeRelationshipType(state, elTaxonRelationship, taxonMap, taxonStore, fromTaxon, success); |
|
268 |
|
|
269 |
if (fromTaxon instanceof Taxon){ |
|
270 |
makeHomotypicSynonymRelations((Taxon)fromTaxon); |
|
271 |
} |
|
272 |
}// end Relationship |
|
273 |
} |
|
274 |
return taxonRelCount; |
|
275 |
} |
|
276 |
|
|
277 |
private int makeTaxonRelationshipAssertion( |
|
278 |
TcsXmlImportState state, |
|
279 |
MapWrapper<TaxonBase> taxonMap, |
|
280 |
MapWrapper<Reference> referenceMap, |
|
281 |
Set<TaxonBase> taxonStore, |
|
282 |
Element elDataSet, |
|
283 |
Namespace tcsNamespace, |
|
284 |
ResultWrapper<Boolean> success){ |
|
285 |
|
|
286 |
int i = 0; |
|
287 |
String childName = "TaxonRelationshipAssertions"; |
|
288 |
boolean obligatory = false; |
|
289 |
Element elTaxonRelationshipAssertions = XmlHelp.getSingleChildElement(success, elDataSet, childName, tcsNamespace, obligatory); |
|
290 |
if(elTaxonRelationshipAssertions == null){ |
|
291 |
return 0; |
|
292 |
} |
|
293 |
|
|
294 |
childName = "TaxonRelationshipAssertion"; |
|
295 |
List<Element> elTaxonRelationshipAssertionList = elTaxonRelationshipAssertions.getChildren(childName, tcsNamespace); |
|
296 |
//for each taxon relationship assertion |
|
297 |
for (Element elTaxonRelationshipAssertion : elTaxonRelationshipAssertionList){ |
|
298 |
if ((i++ % modCount) == 0){ logger.info("TaxonRelationshipAssertions handled: " + (i-1));} |
|
299 |
String strId = elTaxonRelationshipAssertion.getAttributeValue("id"); |
|
300 |
//TODO id |
|
301 |
|
|
302 |
childName = "AccordingTo"; |
|
303 |
obligatory = true; |
|
304 |
Element elAccordingTo = XmlHelp.getSingleChildElement(success, elTaxonRelationshipAssertion, childName, tcsNamespace, obligatory); |
|
305 |
Reference ref = makeAccordingTo(elAccordingTo, referenceMap, success); |
|
306 |
|
|
307 |
childName = "FromTaxonConcept"; |
|
308 |
obligatory = true; |
|
309 |
Element elFromTaxonConcept = XmlHelp.getSingleChildElement(success, elTaxonRelationshipAssertion, childName, tcsNamespace, obligatory); |
|
310 |
|
|
311 |
Class<? extends TaxonBase> clazz = Taxon.class; |
|
312 |
//TODO if synonym |
|
313 |
TaxonBase fromTaxon = makeReferenceType(elFromTaxonConcept, clazz, taxonMap, success); |
|
314 |
|
|
315 |
makeRelationshipType(state, elTaxonRelationshipAssertion, taxonMap, taxonStore, fromTaxon, success); |
|
316 |
}//elTaxonRelationshipAssertion |
|
317 |
|
|
318 |
return i; |
|
319 |
} |
|
320 |
|
|
321 |
|
|
322 |
/** |
|
323 |
* Handles the TCS RelationshipType element. |
|
324 |
* @param tcsConfig |
|
325 |
* @param elRelationship |
|
326 |
* @param taxonMap |
|
327 |
* @param taxonStore |
|
328 |
* @param fromTaxon |
|
329 |
* @param success |
|
330 |
*/ |
|
331 |
private void makeRelationshipType( |
|
332 |
TcsXmlImportState state |
|
333 |
, Element elRelationship |
|
334 |
, MapWrapper<TaxonBase> taxonMap |
|
335 |
, Set<TaxonBase> taxonStore |
|
336 |
, TaxonBase fromTaxon |
|
337 |
, ResultWrapper<Boolean> success |
|
338 |
){ |
|
339 |
|
|
340 |
if (elRelationship == null){ |
|
341 |
success.setValue(false); |
|
342 |
} |
|
343 |
String strRelType = elRelationship.getAttributeValue("type"); |
|
344 |
|
|
345 |
|
|
346 |
try { |
|
347 |
ResultWrapper<Boolean> isInverse = new ResultWrapper<Boolean>(); |
|
348 |
isInverse.setValue(false); |
|
349 |
if ("has vernacular".equalsIgnoreCase(strRelType)){ |
|
350 |
handleVernacular(success, state, elRelationship, fromTaxon); |
|
351 |
}else{ |
|
352 |
RelationshipTermBase<?> relType = TcsXmlTransformer.tcsRelationshipType2Relationship(strRelType, isInverse); |
|
353 |
|
|
354 |
//toTaxon (should be part of relationshipType) |
|
355 |
boolean isSynonym = (relType instanceof SynonymType); |
|
356 |
TaxonBase toTaxon = getToTaxon(elRelationship, taxonMap, state.getMissingConceptLSIDs(), isSynonym, success, state); |
|
357 |
|
|
358 |
if (toTaxon != null && fromTaxon != null){ |
|
359 |
//exchange taxa if relationship is inverse |
|
360 |
if (isInverse.getValue() == true ){ |
|
361 |
TaxonBase tmp = toTaxon; |
|
362 |
toTaxon = fromTaxon; |
|
363 |
fromTaxon = tmp; |
|
364 |
} |
|
365 |
|
|
366 |
//Create relationship |
|
367 |
if (! (toTaxon instanceof Taxon)){ |
|
368 |
logger.warn("TaxonBase toTaxon is not of Type 'Taxon'. Relationship is not added."); |
|
369 |
success.setValue(false); |
|
370 |
}else{ |
|
371 |
Taxon taxonTo = (Taxon)toTaxon; |
|
372 |
if (relType instanceof SynonymType){ |
|
373 |
SynonymType synRelType = (SynonymType)relType; |
|
374 |
if (! (fromTaxon instanceof Synonym )){ |
|
375 |
logger.warn("TaxonBase fromTaxon is not of Type 'Synonym'. Relationship is not added."); |
|
376 |
success.setValue(false); |
|
377 |
}else{ |
|
378 |
Synonym synonym = (Synonym)fromTaxon; |
|
379 |
TaxonName synName = synonym.getName(); |
|
380 |
TaxonName accName = taxonTo.getName(); |
|
381 |
if (synName != null && accName != null && synName.isHomotypic(accName) |
|
382 |
&& ( synRelType.equals(SynonymType.SYNONYM_OF()))){ |
|
383 |
synRelType = SynonymType.HOMOTYPIC_SYNONYM_OF(); |
|
384 |
} |
|
385 |
if (! relationExists(taxonTo, synonym, synRelType)){ |
|
386 |
taxonTo.addSynonym(synonym, synRelType); |
|
387 |
}else{ |
|
388 |
//TODO citation, microReference |
|
389 |
//TODO different synRelTypes -> warning |
|
390 |
success.setValue(false); |
|
391 |
} |
|
392 |
} |
|
393 |
}else if (relType instanceof TaxonRelationshipType){ |
|
394 |
Reference citation = null; |
|
395 |
String microReference = null; |
|
396 |
makeTaxonRelationship(state, (TaxonRelationshipType)relType, fromTaxon, taxonTo, citation, microReference, success); |
|
397 |
}else{ |
|
398 |
logger.warn("Unknown Relationshiptype"); |
|
399 |
success.setValue(false); |
|
400 |
} |
|
401 |
taxonStore.add(toTaxon); |
|
402 |
} |
|
403 |
}else{ |
|
404 |
if (toTaxon == null){ |
|
405 |
// logger.warn("toTaxon (" + /*strToTaxon + */ ") could not be found in taxonMap. Relationship of type " + strRelType + " was not added to CDM"); |
|
406 |
} |
|
407 |
if (fromTaxon == null){ |
|
408 |
// logger.warn("fromTaxon (" + /*strTaxonAbout + */") could not be found in taxonMap. Relationship was not added to CDM"); |
|
409 |
} |
|
410 |
success.setValue(false); |
|
411 |
} |
|
412 |
} |
|
413 |
} catch (UnknownCdmTypeException e) { |
|
414 |
//TODO |
|
415 |
logger.warn("relationshipType " + strRelType + " not yet implemented"); |
|
416 |
success.setValue(false); |
|
417 |
} |
|
418 |
return; |
|
419 |
} |
|
420 |
|
|
421 |
private void handleVernacular(ResultWrapper<Boolean> success, TcsXmlImportState state, Element elRelationship, TaxonBase taxonBase) { |
|
422 |
if (! taxonBase.isInstanceOf(Taxon.class)){ |
|
423 |
logger.warn("From Taxon is not of type Taxon but of type " + taxonBase.getClass().getSimpleName()); |
|
424 |
success.setValue(false); |
|
425 |
return; |
|
426 |
}else{ |
|
427 |
Taxon taxon = CdmBase.deproxy(taxonBase, Taxon.class); |
|
428 |
Map<String, CommonTaxonName> commonNameMap = state.getCommonNameMap(); |
|
429 |
CommonTaxonName commonTaxonName = getCommonName(elRelationship, commonNameMap, success); |
|
430 |
TaxonDescription description = getDescription(taxon); |
|
431 |
description.addElement(commonTaxonName); |
|
432 |
} |
|
433 |
} |
|
434 |
|
|
435 |
private TaxonDescription getDescription(Taxon taxon) { |
|
436 |
if (taxon.getDescriptions().isEmpty()){ |
|
437 |
return TaxonDescription.NewInstance(taxon); |
|
438 |
}else{ |
|
439 |
//TODO only if the description represents this TCS file |
|
440 |
return taxon.getDescriptions().iterator().next(); |
|
441 |
} |
|
442 |
} |
|
443 |
|
|
444 |
private CommonTaxonName getCommonName(Element elTaxonRelationship, Map<String, CommonTaxonName> commonNameMap, ResultWrapper<Boolean> success){ |
|
445 |
CommonTaxonName result = null; |
|
446 |
if (elTaxonRelationship == null || commonNameMap == null){ |
|
447 |
success.setValue(false); |
|
448 |
}else{ |
|
449 |
String childName = "ToTaxonConcept"; |
|
450 |
boolean obligatory = true; |
|
451 |
Element elToTaxonConcept = XmlHelp.getSingleChildElement(success, elTaxonRelationship, childName, elTaxonRelationship.getNamespace(), obligatory); |
|
452 |
|
|
453 |
String linkType = elToTaxonConcept.getAttributeValue("linkType"); |
|
454 |
if (linkType == null || linkType.equals("local")){ |
|
455 |
String ref = elToTaxonConcept.getAttributeValue("ref"); |
|
456 |
if (ref != null){ |
|
457 |
result = commonNameMap.get(ref); |
|
458 |
}else{ |
|
459 |
logger.warn("Non ref not yet implemented for vernacular name relationship"); |
|
460 |
} |
|
461 |
}else{ |
|
462 |
logger.warn("External link types for vernacular name not yet implemented"); |
|
463 |
} |
|
464 |
} |
|
465 |
return result; |
|
466 |
} |
|
467 |
|
|
468 |
private void makeTaxonRelationship(TcsXmlImportState state, TaxonRelationshipType relType, TaxonBase fromTaxon, Taxon taxonTo, Reference citation, String microReference, ResultWrapper<Boolean> success){ |
|
469 |
TaxonRelationshipType taxRelType = relType; |
|
470 |
if (! (fromTaxon instanceof Taxon )){ |
|
471 |
logger.warn("TaxonBase fromTaxon " + /*strTaxonAbout +*/ "is not of Type 'Taxon'. Relationship is not added."); |
|
472 |
success.setValue(false); |
|
473 |
}else{ |
|
474 |
Taxon taxonFrom = (Taxon)fromTaxon; |
|
475 |
if (relType.equals(TaxonRelationshipType.TAXONOMICALLY_INCLUDED_IN())){ |
|
476 |
makeTaxonomicallyIncluded(state, taxonTo, taxonFrom, citation, microReference); |
|
477 |
}else{ |
|
478 |
taxonFrom.addTaxonRelation(taxonTo, taxRelType, citation, microReference); |
|
479 |
} |
|
480 |
} |
|
481 |
} |
|
482 |
|
|
483 |
private boolean makeTaxonomicallyIncluded(TcsXmlImportState state, Taxon toTaxon, Taxon fromTaxon, Reference citation, String microCitation){ |
|
484 |
Reference sec = toTaxon.getSec(); |
|
485 |
Classification tree = state.getTree(sec); |
|
486 |
if (tree == null){ |
|
487 |
tree = makeTree(state, sec); |
|
488 |
} |
|
489 |
TaxonNode childNode = tree.addParentChild(toTaxon, fromTaxon, citation, microCitation); |
|
490 |
return (childNode != null); |
|
491 |
} |
|
492 |
|
|
493 |
|
|
494 |
@SuppressWarnings("rawtypes") |
|
495 |
private TaxonBase getToTaxon(Element elTaxonRelationship, MapWrapper<TaxonBase> map, List<String> missingNameID,boolean isSynonym, ResultWrapper<Boolean> success, TcsXmlImportState state){ |
|
496 |
TaxonBase result = null; |
|
497 |
if (elTaxonRelationship == null || map == null){ |
|
498 |
success.setValue(false); |
|
499 |
}else{ |
|
500 |
String childName = "ToTaxonConcept"; |
|
501 |
boolean obligatory = true; |
|
502 |
Element elToTaxonConcept = XmlHelp.getSingleChildElement(success, elTaxonRelationship, childName, elTaxonRelationship.getNamespace(), obligatory); |
|
503 |
|
|
504 |
|
|
505 |
String linkType = elToTaxonConcept.getAttributeValue("linkType"); |
|
506 |
if (linkType == null || linkType.equals("local")){ |
|
507 |
String ref = elToTaxonConcept.getAttributeValue("ref"); |
|
508 |
if (ref != null){ |
|
509 |
result = map.get(ref); |
|
510 |
if (result == null && state.getConfig().isDoGetMissingNames()){ |
|
511 |
|
|
512 |
|
|
513 |
String[] split= ref.split(":"); |
|
514 |
String id = split[split.length-1]; |
|
515 |
logger.info("get name for id " + id); |
|
516 |
if (missingNameID.contains(id)){ |
|
517 |
return null; |
|
518 |
} |
|
519 |
InputStream nameStream = service.getNamesById(id); |
|
520 |
|
|
521 |
|
|
522 |
try{ |
|
523 |
String nameUri = "urn:lsid:ipni.org:names:"+ id; |
|
524 |
TaxonName name = rdfNameImport.handleRdfElementFromStream(nameStream, rdfConfig, (MapWrapper<TaxonName>)state.getStore(ICdmIO.TAXONNAME_STORE), nameUri); |
|
525 |
if (name != null){ |
|
526 |
if (name.getTaxa().isEmpty()){ |
|
527 |
|
|
528 |
result = Taxon.NewInstance(name, null); |
|
529 |
}else{ |
|
530 |
result = (TaxonBase)name.getTaxa().iterator().next(); |
|
531 |
} |
|
532 |
name.addSource(OriginalSourceType.Import, ref, "TaxonConcept", null, null); |
|
533 |
result.addSource(OriginalSourceType.Import, ref, "TaxonConcept", null, null); |
|
534 |
|
|
535 |
map.put(removeVersionOfRef(ref), result); |
|
536 |
} else{ |
|
537 |
missingNameID.add(id); |
|
538 |
} |
|
539 |
}catch(Exception e){ |
|
540 |
logger.debug(e.getMessage()); |
|
541 |
e.printStackTrace(); |
|
542 |
} |
|
543 |
} |
|
544 |
}else{ |
|
545 |
String title = elToTaxonConcept.getTextNormalize(); |
|
546 |
//TODO synonym? |
|
547 |
TaxonName taxonName = TaxonNameFactory.NewNonViralInstance(null); |
|
548 |
taxonName.setTitleCache(title, true); |
|
549 |
logger.warn("Free text related taxon seems to be bug in TCS"); |
|
550 |
if (isSynonym){ |
|
551 |
result = Synonym.NewInstance(taxonName, TcsXmlTaxonImport.unknownSec()); |
|
552 |
}else{ |
|
553 |
result = Taxon.NewInstance(taxonName, TcsXmlTaxonImport.unknownSec()); |
|
554 |
} |
|
555 |
result.setTitleCache(title, true); |
|
556 |
} |
|
557 |
}else{ |
|
558 |
logger.warn("External link types for synonym not yet implemented"); |
|
559 |
} |
|
560 |
} |
|
561 |
return result; |
|
562 |
} |
|
563 |
|
|
564 |
private boolean relationExists(Taxon taxonTo, Synonym synonym, SynonymType synRelType){ |
|
565 |
if (synonym == null || taxonTo == null |
|
566 |
|| !taxonTo.equals(synonym.getAcceptedTaxon())){ |
|
567 |
return false; |
|
568 |
}else{ |
|
569 |
return CdmUtils.nullSafeEqual(synonym.getType(),synRelType); |
|
570 |
} |
|
571 |
} |
|
572 |
|
|
573 |
private boolean makeHomotypicSynonymRelations(Taxon aboutTaxon){ |
|
574 |
TaxonName aboutName = aboutTaxon.getName(); |
|
575 |
if (aboutName != null){ |
|
576 |
Set<TaxonName> typifiedNames = aboutName.getHomotypicalGroup().getTypifiedNames(); |
|
577 |
for (TaxonName typifiedName : typifiedNames){ |
|
578 |
//TODO check if name is part of this tcs file |
|
579 |
if (typifiedName.equals(aboutName)){ |
|
580 |
continue; |
|
581 |
} |
|
582 |
Set<Synonym> syns = typifiedName.getSynonyms(); |
|
583 |
for(Synonym syn:syns){ |
|
584 |
aboutTaxon.addSynonym(syn, SynonymType.HOMOTYPIC_SYNONYM_OF()); |
|
585 |
} |
|
586 |
} |
|
587 |
} |
|
588 |
return true; |
|
589 |
} |
|
590 |
|
|
591 |
@Override |
|
592 |
protected boolean isIgnore(TcsXmlImportState state){ |
|
593 |
return ! state.getConfig().isDoRelTaxa(); |
|
594 |
} |
|
595 |
} |
|
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.io.InputStream; |
|
13 |
import java.util.ArrayList; |
|
14 |
import java.util.HashSet; |
|
15 |
import java.util.List; |
|
16 |
import java.util.Map; |
|
17 |
import java.util.Set; |
|
18 |
|
|
19 |
import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger; |
|
20 |
import org.jdom.Element; |
|
21 |
import org.jdom.Namespace; |
|
22 |
import org.springframework.beans.factory.annotation.Autowired; |
|
23 |
import org.springframework.stereotype.Component; |
|
24 |
|
|
25 |
import eu.etaxonomy.cdm.common.CdmUtils; |
|
26 |
import eu.etaxonomy.cdm.common.ResultWrapper; |
|
27 |
import eu.etaxonomy.cdm.common.XmlHelp; |
|
28 |
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper; |
|
29 |
import eu.etaxonomy.cdm.io.common.ICdmIO; |
|
30 |
import eu.etaxonomy.cdm.io.common.MapWrapper; |
|
31 |
import eu.etaxonomy.cdm.io.tcsrdf.TcsRdfImportConfigurator; |
|
32 |
import eu.etaxonomy.cdm.io.tcsrdf.TcsRdfTaxonNameImport; |
|
33 |
import eu.etaxonomy.cdm.io.tcsxml.TcsXmlTransformer; |
|
34 |
import eu.etaxonomy.cdm.model.common.CdmBase; |
|
35 |
import eu.etaxonomy.cdm.model.common.RelationshipTermBase; |
|
36 |
import eu.etaxonomy.cdm.model.description.CommonTaxonName; |
|
37 |
import eu.etaxonomy.cdm.model.description.TaxonDescription; |
|
38 |
import eu.etaxonomy.cdm.model.name.TaxonName; |
|
39 |
import eu.etaxonomy.cdm.model.name.TaxonNameFactory; |
|
40 |
import eu.etaxonomy.cdm.model.reference.OriginalSourceType; |
|
41 |
import eu.etaxonomy.cdm.model.reference.Reference; |
|
42 |
import eu.etaxonomy.cdm.model.taxon.Classification; |
|
43 |
import eu.etaxonomy.cdm.model.taxon.Synonym; |
|
44 |
import eu.etaxonomy.cdm.model.taxon.SynonymType; |
|
45 |
import eu.etaxonomy.cdm.model.taxon.Taxon; |
|
46 |
import eu.etaxonomy.cdm.model.taxon.TaxonBase; |
|
47 |
import eu.etaxonomy.cdm.model.taxon.TaxonNode; |
|
48 |
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType; |
|
49 |
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException; |
|
50 |
|
|
51 |
|
|
52 |
/** |
|
53 |
* @author a.mueller |
|
54 |
* |
|
55 |
*/ |
|
56 |
@Component |
|
57 |
public class TcsXmlTaxonRelationsImport extends TcsXmlImportBase implements ICdmIO<TcsXmlImportState> { |
|
58 |
private static final long serialVersionUID = 6632990505515905663L; |
|
59 |
|
|
60 |
private static final Logger logger = LogManager.getLogger(TcsXmlTaxonRelationsImport.class); |
|
61 |
|
|
62 |
private static int modCount = 30000; |
|
63 |
|
|
64 |
@Autowired |
|
65 |
private TcsRdfTaxonNameImport rdfNameImport; |
|
66 |
private TcsRdfImportConfigurator rdfConfig = TcsRdfImportConfigurator.NewInstance(null, null); |
|
67 |
|
|
68 |
public TcsXmlTaxonRelationsImport(){ |
|
69 |
super(); |
|
70 |
|
|
71 |
} |
|
72 |
|
|
73 |
@Override |
|
74 |
public boolean doCheck(TcsXmlImportState state){ |
|
75 |
boolean result = true; |
|
76 |
logger.warn("Checking for TaxonRelations not yet implemented"); |
|
77 |
logger.warn("Creation of homotypic relations is still problematic"); |
|
78 |
//result &= checkArticlesWithoutJournal(bmiConfig); |
|
79 |
//result &= checkPartOfJournal(bmiConfig); |
|
80 |
|
|
81 |
return result; |
|
82 |
} |
|
83 |
|
|
84 |
@Override |
|
85 |
public void doInvoke(TcsXmlImportState state){ |
|
86 |
|
|
87 |
|
|
88 |
logger.info("start make taxon relations ..."); |
|
89 |
MapWrapper<TaxonBase> taxonMap = (MapWrapper<TaxonBase>)state.getStore(ICdmIO.TAXON_STORE); |
|
90 |
MapWrapper<TaxonName> taxonNameMap = (MapWrapper<TaxonName>)state.getStore(ICdmIO.TAXONNAME_STORE); |
|
91 |
MapWrapper<Reference> referenceMap = (MapWrapper<Reference>)state.getStore(ICdmIO.REFERENCE_STORE); |
|
92 |
|
|
93 |
Set<TaxonBase> taxonStore = new HashSet<TaxonBase>(); |
|
94 |
|
|
95 |
ResultWrapper<Boolean> success = ResultWrapper.NewInstance(true); |
|
96 |
String childName; |
|
97 |
boolean obligatory; |
|
98 |
String idNamespace = "TaxonRelationDTO"; |
|
99 |
|
|
100 |
TcsXmlImportConfigurator config = state.getConfig(); |
|
101 |
Element elDataSet = super.getDataSetElement(config); |
|
102 |
Namespace tcsNamespace = config.getTcsXmlNamespace(); |
|
103 |
|
|
104 |
childName = "TaxonConcepts"; |
|
105 |
obligatory = false; |
|
106 |
Element elTaxonConcepts = XmlHelp.getSingleChildElement(success, elDataSet, childName, tcsNamespace, obligatory); |
|
107 |
|
|
108 |
childName = "TaxonConcept"; |
|
109 |
List<Element> elTaxonConceptList = elTaxonConcepts == null ? new ArrayList<Element>() : elTaxonConcepts.getChildren(childName, tcsNamespace); |
|
110 |
|
|
111 |
int i = 0; |
|
112 |
int taxonRelCount = 0; |
|
113 |
|
|
114 |
//for each taxonConcept |
|
115 |
logger.info("NUmber of taxon concepts: " + elTaxonConceptList.size()); |
|
116 |
for (Element elTaxonConcept : elTaxonConceptList){ |
|
117 |
if ((i++ % modCount) == 0){ logger.info("Taxa handled: " + (i-1));} |
|
118 |
taxonRelCount += makeTaxonConcept(state, taxonMap, taxonStore, elTaxonConcept, tcsNamespace, success); |
|
119 |
}//elTaxonConcept |
|
120 |
logger.info("Taxa handled: " + taxonStore.size()); |
|
121 |
//TaxonRelationshipAssertions |
|
122 |
taxonRelCount += makeTaxonRelationshipAssertion(state, taxonMap, referenceMap, taxonStore, elDataSet, tcsNamespace, success); |
|
123 |
|
|
124 |
logger.info("Taxa to save: " + taxonStore.size()); |
|
125 |
getTaxonService().save(taxonStore); |
|
126 |
|
|
127 |
//do basionym relationships |
|
128 |
childName = "TaxonNames"; |
|
129 |
obligatory = false; |
|
130 |
Element elTaxonNames = XmlHelp.getSingleChildElement(success, elDataSet, childName, tcsNamespace, obligatory); |
|
131 |
|
|
132 |
childName = "TaxonName"; |
|
133 |
List<Element> elTaxonNameList = elTaxonNames == null ? new ArrayList<Element>() : elTaxonNames.getChildren(childName, tcsNamespace); |
|
134 |
|
|
135 |
logger.info("NUmber of taxon concepts: " + elTaxonNameList.size()); |
|
136 |
for (Element elTaxonName : elTaxonNameList){ |
|
137 |
if ((i++ % modCount) == 0){ logger.info("Taxa handled: " + (i-1));} |
|
138 |
taxonRelCount += makeBasionymRelations(state, taxonMap, taxonNameMap, taxonStore, elTaxonName, tcsNamespace, success); |
|
139 |
}//elTaxonConcept |
|
140 |
logger.info("Taxa handled: " + taxonStore.size()); |
|
141 |
|
|
142 |
|
|
143 |
taxonStore = null; |
|
144 |
logger.info("end make taxon relations ..."); |
|
145 |
if (!success.getValue()){ |
|
146 |
state.setUnsuccessfull(); |
|
147 |
} |
|
148 |
return; |
|
149 |
} |
|
150 |
|
|
151 |
private int makeBasionymRelations(TcsXmlImportState state, |
|
152 |
MapWrapper<TaxonBase> taxonMap, MapWrapper<TaxonName> taxonNameMap, Set<TaxonBase> taxonStore, |
|
153 |
Element elTaxonName, Namespace tcsNamespace, |
|
154 |
ResultWrapper<Boolean> success) { |
|
155 |
|
|
156 |
/* |
|
157 |
* <tcs:Basionym> |
|
158 |
<tcs:RelatedName ref="urn:lsid:ipni.org:names:50000063-1">Caryophyllaceae</tcs:RelatedName> |
|
159 |
</tcs:Basionym> |
|
160 |
*/ |
|
161 |
|
|
162 |
|
|
163 |
String childName = "Basionym"; |
|
164 |
boolean obligatory = false; |
|
165 |
Element elBasionymRelationships = XmlHelp.getSingleChildElement(success, elTaxonName, childName, tcsNamespace, obligatory); |
|
166 |
if (elBasionymRelationships != null){ |
|
167 |
childName = "RelatedName"; |
|
168 |
obligatory = false; |
|
169 |
Element elBasionym = XmlHelp.getSingleChildElement(success, elBasionymRelationships, childName, tcsNamespace, obligatory); |
|
170 |
|
|
171 |
String id = elTaxonName.getAttributeValue("id"); |
|
172 |
TaxonName name = taxonNameMap.get(removeVersionOfRef(id)); |
|
173 |
|
|
174 |
TaxonBase taxonBase = (TaxonBase)name.getTaxonBases().iterator().next(); |
|
175 |
|
|
176 |
String ref = elBasionym.getAttributeValue("ref"); |
|
177 |
TaxonName basionymName = taxonNameMap.get(removeVersionOfRef(ref)); |
|
178 |
|
|
179 |
if (basionymName != null){ |
|
180 |
basionymName = HibernateProxyHelper.deproxy(basionymName, TaxonName.class); |
|
181 |
TaxonBase basionym; |
|
182 |
if (basionymName.getTaxonBases().isEmpty()){ |
|
183 |
basionym = Synonym.NewInstance(basionymName, null); |
|
184 |
}else{ |
|
185 |
basionym = (TaxonBase)basionymName.getTaxonBases().iterator().next(); |
|
186 |
} |
|
187 |
//Synonym basionymSyn; |
|
188 |
if (basionym instanceof Taxon){ |
|
189 |
|
|
190 |
if (!(taxonBase instanceof Synonym)){ |
|
191 |
logger.debug("The taxon " + basionymName.getTitleCache() + " is used in a concept and can not be a synonym " + name.getTitleCache() + "but will be added as basionym for the homotypical group"); |
|
192 |
name.addBasionym(basionymName); |
|
193 |
//basionymName.getHomotypicalGroup().addTypifiedName(name); |
|
194 |
} else if (taxonBase instanceof Synonym){ |
|
195 |
Synonym synonym = (Synonym) taxonBase; |
|
196 |
((Taxon)basionym).addSynonym(synonym, SynonymType.HOMOTYPIC_SYNONYM_OF()); |
|
197 |
basionym.getHomotypicGroup().setGroupBasionym(basionymName); |
|
198 |
taxonStore.add(basionym); |
|
199 |
} |
|
200 |
}else{ |
|
201 |
if (taxonBase instanceof Taxon){ |
|
202 |
Synonym synonym = (Synonym) basionym; |
|
203 |
((Taxon)taxonBase).addSynonym(synonym, SynonymType.HOMOTYPIC_SYNONYM_OF()); |
|
204 |
taxonBase.getHomotypicGroup().setGroupBasionym(basionymName); |
|
205 |
taxonStore.add(taxonBase); |
|
206 |
} else{ |
|
207 |
Taxon acc = ((Synonym)taxonBase).getAcceptedTaxon(); |
|
208 |
if (acc != null){ |
|
209 |
acc.addHomotypicSynonym((Synonym)basionym); |
|
210 |
basionymName.getHomotypicalGroup().setGroupBasionym(basionymName); |
|
211 |
} |
|
212 |
} |
|
213 |
} |
|
214 |
|
|
215 |
|
|
216 |
} else{ |
|
217 |
basionymName = TaxonNameFactory.NewNonViralInstance(name.getRank()); |
|
218 |
childName = "RelatedName"; |
|
219 |
obligatory = true; |
|
220 |
Element elName = XmlHelp.getSingleChildElement(success, elBasionym, childName, tcsNamespace, obligatory); |
|
221 |
String strName = (elName == null)? "" : elName.getTextNormalize(); |
|
222 |
basionymName.setTitleCache(strName, false); |
|
223 |
Synonym basionymSyn = Synonym.NewInstance(basionymName, unknownSec()); |
|
224 |
if (taxonBase instanceof Taxon){ |
|
225 |
Taxon taxon = (Taxon)taxonBase; |
|
226 |
taxon.addSynonym(basionymSyn, SynonymType.HOMOTYPIC_SYNONYM_OF()); |
|
227 |
taxon.getHomotypicGroup().setGroupBasionym(basionymName); |
|
228 |
taxonStore.add(taxon); |
|
229 |
} else{ |
|
230 |
Synonym syn = (Synonym) taxonBase; |
|
231 |
if (syn.getAcceptedTaxon() != null){ |
|
232 |
Taxon accTaxon = syn.getAcceptedTaxon(); |
|
233 |
accTaxon.addSynonym(basionymSyn, SynonymType.HOMOTYPIC_SYNONYM_OF()); |
|
234 |
accTaxon.getHomotypicGroup().setGroupBasionym(basionymName); |
|
235 |
taxonStore.add(accTaxon); |
|
236 |
} |
|
237 |
} |
|
238 |
} |
|
239 |
} |
|
240 |
return 1; |
|
241 |
} |
|
242 |
|
|
243 |
private int makeTaxonConcept(TcsXmlImportState state, MapWrapper<TaxonBase> taxonMap, Set<TaxonBase> taxonStore, Element elTaxonConcept, Namespace tcsNamespace, ResultWrapper<Boolean> success){ |
|
244 |
int taxonRelCount = 0; |
|
245 |
|
|
246 |
String childName = "TaxonRelationships"; |
|
247 |
boolean obligatory = false; |
|
248 |
Element elTaxonRelationships = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory); |
|
249 |
|
|
250 |
if (elTaxonRelationships != null){ |
|
251 |
//Relationships |
|
252 |
String tcsElementName = "TaxonRelationship"; |
|
253 |
List<Element> elTaxonRelationshipList = elTaxonRelationships.getChildren(tcsElementName, tcsNamespace); |
|
254 |
logger.info("Number of taxonrelationships: " + elTaxonRelationshipList.size()); |
|
255 |
for (Element elTaxonRelationship: elTaxonRelationshipList){ |
|
256 |
|
|
257 |
taxonRelCount++; |
|
258 |
logger.debug("TaxonRelationship "+ taxonRelCount); |
|
259 |
|
|
260 |
String strId = elTaxonConcept.getAttributeValue("id"); |
|
261 |
//TODO |
|
262 |
// String strConceptType = elTaxonConcept.getAttributeValue("type"); //original, revision, incomplete, aggregate, nominal |
|
263 |
// 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. |
|
264 |
// String strForm = elTaxonConcept.getAttributeValue("form"); //anamorph, teleomorph, hybrid |
|
265 |
|
|
266 |
TaxonBase fromTaxon = taxonMap.get(removeVersionOfRef(strId)); |
|
267 |
makeRelationshipType(state, elTaxonRelationship, taxonMap, taxonStore, fromTaxon, success); |
|
268 |
|
|
269 |
if (fromTaxon instanceof Taxon){ |
|
270 |
makeHomotypicSynonymRelations((Taxon)fromTaxon); |
|
271 |
} |
|
272 |
}// end Relationship |
|
273 |
} |
|
274 |
return taxonRelCount; |
|
275 |
} |
|
276 |
|
|
277 |
private int makeTaxonRelationshipAssertion( |
|
278 |
TcsXmlImportState state, |
|
279 |
MapWrapper<TaxonBase> taxonMap, |
|
280 |
MapWrapper<Reference> referenceMap, |
|
281 |
Set<TaxonBase> taxonStore, |
|
282 |
Element elDataSet, |
|
283 |
Namespace tcsNamespace, |
|
284 |
ResultWrapper<Boolean> success){ |
|
285 |
|
|
286 |
int i = 0; |
|
287 |
String childName = "TaxonRelationshipAssertions"; |
|
288 |
boolean obligatory = false; |
|
289 |
Element elTaxonRelationshipAssertions = XmlHelp.getSingleChildElement(success, elDataSet, childName, tcsNamespace, obligatory); |
|
290 |
if(elTaxonRelationshipAssertions == null){ |
|
291 |
return 0; |
|
292 |
} |
|
293 |
|
|
294 |
childName = "TaxonRelationshipAssertion"; |
|
295 |
List<Element> elTaxonRelationshipAssertionList = elTaxonRelationshipAssertions.getChildren(childName, tcsNamespace); |
|
296 |
//for each taxon relationship assertion |
|
297 |
for (Element elTaxonRelationshipAssertion : elTaxonRelationshipAssertionList){ |
|
298 |
if ((i++ % modCount) == 0){ logger.info("TaxonRelationshipAssertions handled: " + (i-1));} |
|
299 |
String strId = elTaxonRelationshipAssertion.getAttributeValue("id"); |
|
300 |
//TODO id |
|
301 |
|
|
302 |
childName = "AccordingTo"; |
|
303 |
obligatory = true; |
|
304 |
Element elAccordingTo = XmlHelp.getSingleChildElement(success, elTaxonRelationshipAssertion, childName, tcsNamespace, obligatory); |
|
305 |
Reference ref = makeAccordingTo(elAccordingTo, referenceMap, success); |
|
306 |
|
|
307 |
childName = "FromTaxonConcept"; |
|
308 |
obligatory = true; |
|
309 |
Element elFromTaxonConcept = XmlHelp.getSingleChildElement(success, elTaxonRelationshipAssertion, childName, tcsNamespace, obligatory); |
|
310 |
|
|
311 |
Class<? extends TaxonBase> clazz = Taxon.class; |
|
312 |
//TODO if synonym |
|
313 |
TaxonBase fromTaxon = makeReferenceType(elFromTaxonConcept, clazz, taxonMap, success); |
|
314 |
|
|
315 |
makeRelationshipType(state, elTaxonRelationshipAssertion, taxonMap, taxonStore, fromTaxon, success); |
|
316 |
}//elTaxonRelationshipAssertion |
|
317 |
|
|
318 |
return i; |
|
319 |
} |
|
320 |
|
|
321 |
|
|
322 |
/** |
|
323 |
* Handles the TCS RelationshipType element. |
|
324 |
* @param tcsConfig |
|
325 |
* @param elRelationship |
|
326 |
* @param taxonMap |
|
327 |
* @param taxonStore |
|
328 |
* @param fromTaxon |
|
329 |
* @param success |
|
330 |
*/ |
|
331 |
private void makeRelationshipType( |
|
332 |
TcsXmlImportState state |
|
333 |
, Element elRelationship |
|
334 |
, MapWrapper<TaxonBase> taxonMap |
|
335 |
, Set<TaxonBase> taxonStore |
|
336 |
, TaxonBase fromTaxon |
|
337 |
, ResultWrapper<Boolean> success |
|
338 |
){ |
|
339 |
|
|
340 |
if (elRelationship == null){ |
|
341 |
success.setValue(false); |
|
342 |
} |
|
343 |
String strRelType = elRelationship.getAttributeValue("type"); |
|
344 |
|
|
345 |
|
|
346 |
try { |
|
347 |
ResultWrapper<Boolean> isInverse = new ResultWrapper<Boolean>(); |
|
348 |
isInverse.setValue(false); |
|
349 |
if ("has vernacular".equalsIgnoreCase(strRelType)){ |
|
350 |
handleVernacular(success, state, elRelationship, fromTaxon); |
|
351 |
}else{ |
|
352 |
RelationshipTermBase<?> relType = TcsXmlTransformer.tcsRelationshipType2Relationship(strRelType, isInverse); |
|
353 |
|
|
354 |
//toTaxon (should be part of relationshipType) |
|
355 |
boolean isSynonym = (relType instanceof SynonymType); |
|
356 |
TaxonBase toTaxon = getToTaxon(elRelationship, taxonMap, state.getMissingConceptLSIDs(), isSynonym, success, state); |
|
357 |
|
|
358 |
if (toTaxon != null && fromTaxon != null){ |
|
359 |
//exchange taxa if relationship is inverse |
|
360 |
if (isInverse.getValue() == true ){ |
|
361 |
TaxonBase tmp = toTaxon; |
|
362 |
toTaxon = fromTaxon; |
|
363 |
fromTaxon = tmp; |
|
364 |
} |
|
365 |
|
|
366 |
//Create relationship |
|
367 |
if (! (toTaxon instanceof Taxon)){ |
|
368 |
logger.warn("TaxonBase toTaxon is not of Type 'Taxon'. Relationship is not added."); |
|
369 |
success.setValue(false); |
|
370 |
}else{ |
|
371 |
Taxon taxonTo = (Taxon)toTaxon; |
|
372 |
if (relType instanceof SynonymType){ |
|
373 |
SynonymType synRelType = (SynonymType)relType; |
|
374 |
if (! (fromTaxon instanceof Synonym )){ |
|
375 |
logger.warn("TaxonBase fromTaxon is not of Type 'Synonym'. Relationship is not added."); |
|
376 |
success.setValue(false); |
|
377 |
}else{ |
|
378 |
Synonym synonym = (Synonym)fromTaxon; |
|
379 |
TaxonName synName = synonym.getName(); |
|
380 |
TaxonName accName = taxonTo.getName(); |
|
381 |
if (synName != null && accName != null && synName.isHomotypic(accName) |
|
382 |
&& ( synRelType.equals(SynonymType.SYNONYM_OF()))){ |
|
383 |
synRelType = SynonymType.HOMOTYPIC_SYNONYM_OF(); |
|
384 |
} |
|
385 |
if (! relationExists(taxonTo, synonym, synRelType)){ |
|
386 |
taxonTo.addSynonym(synonym, synRelType); |
|
387 |
}else{ |
|
388 |
//TODO citation, microReference |
|
389 |
//TODO different synRelTypes -> warning |
|
390 |
success.setValue(false); |
|
391 |
} |
|
392 |
} |
|
393 |
}else if (relType instanceof TaxonRelationshipType){ |
|
394 |
Reference citation = null; |
|
395 |
String microReference = null; |
|
396 |
makeTaxonRelationship(state, (TaxonRelationshipType)relType, fromTaxon, taxonTo, citation, microReference, success); |
|
397 |
}else{ |
|
398 |
logger.warn("Unknown Relationshiptype"); |
|
399 |
success.setValue(false); |
|
400 |
} |
|
401 |
taxonStore.add(toTaxon); |
|
402 |
} |
|
403 |
}else{ |
|
404 |
if (toTaxon == null){ |
|
405 |
// logger.warn("toTaxon (" + /*strToTaxon + */ ") could not be found in taxonMap. Relationship of type " + strRelType + " was not added to CDM"); |
|
406 |
} |
|
407 |
if (fromTaxon == null){ |
|
408 |
// logger.warn("fromTaxon (" + /*strTaxonAbout + */") could not be found in taxonMap. Relationship was not added to CDM"); |
|
409 |
} |
|
410 |
success.setValue(false); |
|
411 |
} |
|
412 |
} |
|
413 |
} catch (UnknownCdmTypeException e) { |
|
414 |
//TODO |
|
415 |
logger.warn("relationshipType " + strRelType + " not yet implemented"); |
|
416 |
success.setValue(false); |
|
417 |
} |
|
418 |
return; |
|
419 |
} |
|
420 |
|
|
421 |
private void handleVernacular(ResultWrapper<Boolean> success, TcsXmlImportState state, Element elRelationship, TaxonBase taxonBase) { |
|
422 |
if (! taxonBase.isInstanceOf(Taxon.class)){ |
|
423 |
logger.warn("From Taxon is not of type Taxon but of type " + taxonBase.getClass().getSimpleName()); |
|
424 |
success.setValue(false); |
|
425 |
return; |
|
426 |
}else{ |
|
427 |
Taxon taxon = CdmBase.deproxy(taxonBase, Taxon.class); |
|
428 |
Map<String, CommonTaxonName> commonNameMap = state.getCommonNameMap(); |
|
429 |
CommonTaxonName commonTaxonName = getCommonName(elRelationship, commonNameMap, success); |
|
430 |
TaxonDescription description = getDescription(taxon); |
|
431 |
description.addElement(commonTaxonName); |
|
432 |
} |
|
433 |
} |
|
434 |
|
|
435 |
private TaxonDescription getDescription(Taxon taxon) { |
|
436 |
if (taxon.getDescriptions().isEmpty()){ |
|
437 |
return TaxonDescription.NewInstance(taxon); |
|
438 |
}else{ |
|
439 |
//TODO only if the description represents this TCS file |
|
440 |
return taxon.getDescriptions().iterator().next(); |
|
441 |
} |
|
442 |
} |
|
443 |
|
|
444 |
private CommonTaxonName getCommonName(Element elTaxonRelationship, Map<String, CommonTaxonName> commonNameMap, ResultWrapper<Boolean> success){ |
|
445 |
CommonTaxonName result = null; |
|
446 |
if (elTaxonRelationship == null || commonNameMap == null){ |
|
447 |
success.setValue(false); |
|
448 |
}else{ |
|
449 |
String childName = "ToTaxonConcept"; |
|
450 |
boolean obligatory = true; |
|
451 |
Element elToTaxonConcept = XmlHelp.getSingleChildElement(success, elTaxonRelationship, childName, elTaxonRelationship.getNamespace(), obligatory); |
|
452 |
|
|
453 |
String linkType = elToTaxonConcept.getAttributeValue("linkType"); |
|
454 |
if (linkType == null || linkType.equals("local")){ |
|
455 |
String ref = elToTaxonConcept.getAttributeValue("ref"); |
|
456 |
if (ref != null){ |
|
457 |
result = commonNameMap.get(ref); |
|
458 |
}else{ |
|
459 |
logger.warn("Non ref not yet implemented for vernacular name relationship"); |
|
460 |
} |
|
461 |
}else{ |
|
462 |
logger.warn("External link types for vernacular name not yet implemented"); |
|
463 |
} |
|
464 |
} |
|
465 |
return result; |
|
466 |
} |
|
467 |
|
|
468 |
private void makeTaxonRelationship(TcsXmlImportState state, TaxonRelationshipType relType, TaxonBase fromTaxon, Taxon taxonTo, Reference citation, String microReference, ResultWrapper<Boolean> success){ |
|
469 |
TaxonRelationshipType taxRelType = relType; |
|
470 |
if (! (fromTaxon instanceof Taxon )){ |
|
471 |
logger.warn("TaxonBase fromTaxon " + /*strTaxonAbout +*/ "is not of Type 'Taxon'. Relationship is not added."); |
|
472 |
success.setValue(false); |
|
473 |
}else{ |
|
474 |
Taxon taxonFrom = (Taxon)fromTaxon; |
|
475 |
if (relType.equals(TaxonRelationshipType.TAXONOMICALLY_INCLUDED_IN())){ |
|
476 |
makeTaxonomicallyIncluded(state, taxonTo, taxonFrom, citation, microReference); |
|
477 |
}else{ |
|
478 |
taxonFrom.addTaxonRelation(taxonTo, taxRelType, citation, microReference); |
|
479 |
} |
|
480 |
} |
|
481 |
} |
|
482 |
|
|
483 |
private boolean makeTaxonomicallyIncluded(TcsXmlImportState state, Taxon toTaxon, Taxon fromTaxon, Reference citation, String microCitation){ |
|
484 |
Reference sec = toTaxon.getSec(); |
|
485 |
Classification tree = state.getTree(sec); |
|
486 |
if (tree == null){ |
|
487 |
tree = makeTree(state, sec); |
|
488 |
} |
|
489 |
TaxonNode childNode = tree.addParentChild(toTaxon, fromTaxon, citation, microCitation); |
|
490 |
return (childNode != null); |
|
491 |
} |
|
492 |
|
|
493 |
|
|
494 |
@SuppressWarnings("rawtypes") |
|
495 |
private TaxonBase getToTaxon(Element elTaxonRelationship, MapWrapper<TaxonBase> map, List<String> missingNameID,boolean isSynonym, ResultWrapper<Boolean> success, TcsXmlImportState state){ |
|
496 |
TaxonBase result = null; |
|
497 |
if (elTaxonRelationship == null || map == null){ |
|
498 |
success.setValue(false); |
|
499 |
}else{ |
|
500 |
String childName = "ToTaxonConcept"; |
|
501 |
boolean obligatory = true; |
|
502 |
Element elToTaxonConcept = XmlHelp.getSingleChildElement(success, elTaxonRelationship, childName, elTaxonRelationship.getNamespace(), obligatory); |
|
503 |
|
|
504 |
|
|
505 |
String linkType = elToTaxonConcept.getAttributeValue("linkType"); |
|
506 |
if (linkType == null || linkType.equals("local")){ |
|
507 |
String ref = elToTaxonConcept.getAttributeValue("ref"); |
|
508 |
if (ref != null){ |
|
509 |
result = map.get(ref); |
|
510 |
if (result == null && state.getConfig().isDoGetMissingNames()){ |
|
511 |
|
|
512 |
|
|
513 |
String[] split= ref.split(":"); |
|
514 |
String id = split[split.length-1]; |
|
515 |
logger.info("get name for id " + id); |
|
516 |
if (missingNameID.contains(id)){ |
|
517 |
return null; |
|
518 |
} |
|
519 |
InputStream nameStream = service.getNamesById(id); |
|
520 |
|
|
521 |
|
|
522 |
try{ |
|
523 |
String nameUri = "urn:lsid:ipni.org:names:"+ id; |
|
524 |
TaxonName name = rdfNameImport.handleRdfElementFromStream(nameStream, rdfConfig, (MapWrapper<TaxonName>)state.getStore(ICdmIO.TAXONNAME_STORE), nameUri); |
|
525 |
if (name != null){ |
|
526 |
if (name.getTaxa().isEmpty()){ |
|
527 |
|
|
528 |
result = Taxon.NewInstance(name, null); |
|
529 |
}else{ |
|
530 |
result = (TaxonBase)name.getTaxa().iterator().next(); |
|
531 |
} |
|
532 |
name.addSource(OriginalSourceType.Import, ref, "TaxonConcept", null, null); |
|
533 |
result.addSource(OriginalSourceType.Import, ref, "TaxonConcept", null, null); |
|
534 |
|
|
535 |
map.put(removeVersionOfRef(ref), result); |
|
536 |
} else{ |
|
537 |
missingNameID.add(id); |
|
538 |
} |
|
539 |
}catch(Exception e){ |
|
540 |
logger.debug(e.getMessage()); |
|
541 |
e.printStackTrace(); |
|
542 |
} |
|
543 |
} |
|
544 |
}else{ |
|
545 |
String title = elToTaxonConcept.getTextNormalize(); |
|
546 |
//TODO synonym? |
|
547 |
TaxonName taxonName = TaxonNameFactory.NewNonViralInstance(null); |
|
548 |
taxonName.setTitleCache(title, true); |
|
549 |
logger.warn("Free text related taxon seems to be bug in TCS"); |
|
550 |
if (isSynonym){ |
|
551 |
result = Synonym.NewInstance(taxonName, TcsXmlTaxonImport.unknownSec()); |
|
552 |
}else{ |
|
553 |
result = Taxon.NewInstance(taxonName, TcsXmlTaxonImport.unknownSec()); |
|
554 |
} |
|
555 |
result.setTitleCache(title, true); |
|
556 |
} |
|
557 |
}else{ |
|
558 |
logger.warn("External link types for synonym not yet implemented"); |
|
559 |
} |
|
560 |
} |
|
561 |
return result; |
|
562 |
} |
|
563 |
|
|
564 |
private boolean relationExists(Taxon taxonTo, Synonym synonym, SynonymType synRelType){ |
|
565 |
if (synonym == null || taxonTo == null |
|
566 |
|| !taxonTo.equals(synonym.getAcceptedTaxon())){ |
|
567 |
return false; |
|
568 |
}else{ |
|
569 |
return CdmUtils.nullSafeEqual(synonym.getType(),synRelType); |
|
570 |
} |
|
571 |
} |
|
572 |
|
|
573 |
private boolean makeHomotypicSynonymRelations(Taxon aboutTaxon){ |
|
574 |
TaxonName aboutName = aboutTaxon.getName(); |
|
575 |
if (aboutName != null){ |
|
576 |
Set<TaxonName> typifiedNames = aboutName.getHomotypicalGroup().getTypifiedNames(); |
|
577 |
for (TaxonName typifiedName : typifiedNames){ |
|
578 |
//TODO check if name is part of this tcs file |
|
579 |
if (typifiedName.equals(aboutName)){ |
|
580 |
continue; |
|
581 |
} |
|
582 |
Set<Synonym> syns = typifiedName.getSynonyms(); |
|
583 |
for(Synonym syn:syns){ |
|
584 |
aboutTaxon.addSynonym(syn, SynonymType.HOMOTYPIC_SYNONYM_OF()); |
|
585 |
} |
|
586 |
} |
|
587 |
} |
|
588 |
return true; |
|
589 |
} |
|
590 |
|
|
591 |
@Override |
|
592 |
protected boolean isIgnore(TcsXmlImportState state){ |
|
593 |
return ! state.getConfig().isDoRelTaxa(); |
|
594 |
} |
|
595 |
} |
Also available in: Unified diff
minor