1
2
3
4
5
6
7
8
9
10 package eu.etaxonomy.cdm.io.tcsxml.in;
11
12 import java.util.HashSet;
13 import java.util.List;
14 import java.util.Set;
15
16 import org.apache.log4j.Logger;
17 import org.jdom.Element;
18 import org.jdom.Namespace;
19 import org.springframework.stereotype.Component;
20
21 import eu.etaxonomy.cdm.common.ResultWrapper;
22 import eu.etaxonomy.cdm.common.XmlHelp;
23 import eu.etaxonomy.cdm.io.common.ICdmIO;
24 import eu.etaxonomy.cdm.io.common.MapWrapper;
25 import eu.etaxonomy.cdm.io.tcsxml.TcsXmlTransformer;
26 import eu.etaxonomy.cdm.model.common.RelationshipTermBase;
27 import eu.etaxonomy.cdm.model.name.NonViralName;
28 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
29 import eu.etaxonomy.cdm.model.reference.ReferenceBase;
30 import eu.etaxonomy.cdm.model.taxon.Synonym;
31 import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
32 import eu.etaxonomy.cdm.model.taxon.Taxon;
33 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
34 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
35 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
36 import eu.etaxonomy.cdm.model.taxon.TaxonomicTree;
37 import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
38
39
40
41
42
43
44 @Component
45 public class TcsXmlTaxonRelationsImport extends TcsXmlImportBase implements ICdmIO<TcsXmlImportState> {
46 private static final Logger logger = Logger.getLogger(TcsXmlTaxonRelationsImport.class);
47
48 private static int modCount = 30000;
49
50 public TcsXmlTaxonRelationsImport(){
51 super();
52 }
53
54 @Override
55 public boolean doCheck(TcsXmlImportState state){
56 boolean result = true;
57 logger.warn("Checking for TaxonRelations not yet implemented");
58 logger.warn("Creation of homotypic relations is still problematic");
59
60
61
62 return result;
63 }
64
65 @Override
66 public boolean doInvoke(TcsXmlImportState state){
67
68
69 logger.info("start make taxon relations ...");
70 MapWrapper<TaxonBase> taxonMap = (MapWrapper<TaxonBase>)state.getStore(ICdmIO.TAXON_STORE);
71 MapWrapper<TaxonNameBase<?,?>> taxonNameMap = (MapWrapper<TaxonNameBase<?,?>>)state.getStore(ICdmIO.TAXONNAME_STORE);
72 MapWrapper<ReferenceBase> referenceMap = (MapWrapper<ReferenceBase>)state.getStore(ICdmIO.REFERENCE_STORE);
73
74 Set<TaxonBase> taxonStore = new HashSet<TaxonBase>();
75
76 ResultWrapper<Boolean> success = ResultWrapper.NewInstance(true);
77 String childName;
78 boolean obligatory;
79 String idNamespace = "TaxonRelation";
80
81 TcsXmlImportConfigurator config = state.getConfig();
82 Element elDataSet = super.getDataSetElement(config);
83 Namespace tcsNamespace = config.getTcsXmlNamespace();
84
85 childName = "TaxonConcepts";
86 obligatory = false;
87 Element elTaxonConcepts = XmlHelp.getSingleChildElement(success, elDataSet, childName, tcsNamespace, obligatory);
88
89 childName = "TaxonConcept";
90 List<Element> elTaxonConceptList = elTaxonConcepts.getChildren(childName, tcsNamespace);
91
92 int i = 0;
93 int taxonRelCount = 0;
94
95
96 for (Element elTaxonConcept : elTaxonConceptList){
97 if ((i++ % modCount) == 0){ logger.info("Taxa handled: " + (i-1));}
98 taxonRelCount += makeTaxonConcept(state, taxonMap, taxonStore, elTaxonConcept, tcsNamespace, success);
99 }
100
101
102 taxonRelCount += makeTaxonRelationshipAssertion(state, taxonMap, referenceMap, taxonStore, elDataSet, tcsNamespace, success);
103
104 logger.info("Taxa to save: " + taxonStore.size());
105 getTaxonService().save(taxonStore);
106
107 logger.info("end make taxon relations ...");
108 return success.getValue();
109 }
110
111 private int makeTaxonConcept(TcsXmlImportState state, MapWrapper<TaxonBase> taxonMap, Set<TaxonBase> taxonStore, Element elTaxonConcept, Namespace tcsNamespace, ResultWrapper<Boolean> success){
112 int taxonRelCount = 0;
113
114 String childName = "TaxonRelationships";
115 boolean obligatory = false;
116 Element elTaxonRelationships = XmlHelp.getSingleChildElement(success, elTaxonConcept, childName, tcsNamespace, obligatory);
117
118 if (elTaxonRelationships != null){
119
120 String tcsElementName = "TaxonRelationship";
121 List<Element> elTaxonRelationshipList = elTaxonRelationships.getChildren(tcsElementName, tcsNamespace);
122
123 for (Element elTaxonRelationship: elTaxonRelationshipList){
124 taxonRelCount++;
125 logger.debug("TaxonRelationship "+ taxonRelCount);
126
127 String strId = elTaxonConcept.getAttributeValue("id");
128
129
130
131
132
133 TaxonBase fromTaxon = taxonMap.get(strId);
134 makeRelationshipType(state, elTaxonRelationship, taxonMap, taxonStore, fromTaxon, success);
135
136 if (fromTaxon instanceof Taxon){
137 makeHomotypicSynonymRelations((Taxon)fromTaxon);
138 }
139 }
140 }
141 return taxonRelCount;
142 }
143
144 private int makeTaxonRelationshipAssertion(
145 TcsXmlImportState state,
146 MapWrapper<TaxonBase> taxonMap,
147 MapWrapper<ReferenceBase> referenceMap,
148 Set<TaxonBase> taxonStore,
149 Element elDataSet,
150 Namespace tcsNamespace,
151 ResultWrapper<Boolean> success){
152
153 int i = 0;
154 String childName = "TaxonRelationshipAssertions";
155 boolean obligatory = false;
156 Element elTaxonRelationshipAssertions = XmlHelp.getSingleChildElement(success, elDataSet, childName, tcsNamespace, obligatory);
157 if(elTaxonRelationshipAssertions == null){
158 return 0;
159 }
160
161 childName = "TaxonRelationshipAssertion";
162 List<Element> elTaxonRelationshipAssertionList = elTaxonRelationshipAssertions.getChildren(childName, tcsNamespace);
163
164 for (Element elTaxonRelationshipAssertion : elTaxonRelationshipAssertionList){
165 if ((i++ % modCount) == 0){ logger.info("TaxonRelationshipAssertions handled: " + (i-1));}
166 String strId = elTaxonRelationshipAssertion.getAttributeValue("id");
167
168
169 childName = "AccordingTo";
170 obligatory = true;
171 Element elAccordingTo = XmlHelp.getSingleChildElement(success, elTaxonRelationshipAssertion, childName, tcsNamespace, obligatory);
172 ReferenceBase ref = makeAccordingTo(elAccordingTo, referenceMap, success);
173
174 childName = "FromTaxonConcept";
175 obligatory = true;
176 Element elFromTaxonConcept = XmlHelp.getSingleChildElement(success, elTaxonRelationshipAssertion, childName, tcsNamespace, obligatory);
177
178 Class<? extends TaxonBase> clazz = Taxon.class;
179
180 TaxonBase fromTaxon = makeReferenceType(elFromTaxonConcept, clazz, taxonMap, success);
181
182 makeRelationshipType(state, elTaxonRelationshipAssertion, taxonMap, taxonStore, fromTaxon, success);
183 }
184
185 return i;
186 }
187
188
189
190
191
192
193
194
195
196
197
198 private void makeRelationshipType(
199 TcsXmlImportState state
200 , Element elRelationship
201 , MapWrapper<TaxonBase> taxonMap
202 , Set<TaxonBase> taxonStore
203 , TaxonBase fromTaxon
204 , ResultWrapper<Boolean> success
205 ){
206
207 if (elRelationship == null){
208 success.setValue(false);
209 }
210 String strRelType = elRelationship.getAttributeValue("type");
211
212
213 try {
214 ResultWrapper<Boolean> isInverse = new ResultWrapper<Boolean>();
215 isInverse.setValue(false);
216 RelationshipTermBase<?> relType = TcsXmlTransformer.tcsRelationshipType2Relationship(strRelType, isInverse);
217
218
219 boolean isSynonym = (relType instanceof SynonymRelationshipType);
220 TaxonBase toTaxon = getToTaxon(elRelationship, taxonMap, isSynonym, success);
221
222 if (toTaxon != null && fromTaxon != null){
223
224 if (isInverse.getValue() == true ){
225 TaxonBase tmp = toTaxon;
226 toTaxon = fromTaxon;
227 fromTaxon = tmp;
228 }
229
230
231 if (! (toTaxon instanceof Taxon)){
232 logger.warn("TaxonBase toTaxon is not of Type 'Taxon'. Relationship is not added.");
233 success.setValue(false);
234 }else{
235 Taxon taxonTo = (Taxon)toTaxon;
236 ReferenceBase citation = null;
237 String microReference = null;
238 if (relType instanceof SynonymRelationshipType){
239 SynonymRelationshipType synRelType = (SynonymRelationshipType)relType;
240 if (! (fromTaxon instanceof Synonym )){
241 logger.warn("TaxonBase fromTaxon is not of Type 'Synonym'. Relationship is not added.");
242 success.setValue(false);
243 }else{
244 Synonym synonym = (Synonym)fromTaxon;
245 TaxonNameBase<?,?> synName = synonym.getName();
246 TaxonNameBase<?,?> accName = taxonTo.getName();
247 if (synName != null && accName != null && synName.isHomotypic(accName)
248 && ( synRelType.equals(SynonymRelationshipType.SYNONYM_OF()))){
249 synRelType = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();
250 }
251 if (! relationExists(taxonTo, synonym, synRelType)){
252 taxonTo.addSynonym(synonym, synRelType, citation, microReference);
253 }else{
254
255
256 success.setValue(false);
257 }
258 }
259 }else if (relType instanceof TaxonRelationshipType){
260 makeTaxonRelationship(state, (TaxonRelationshipType)relType, fromTaxon, taxonTo, citation, microReference, success);
261 }else{
262 logger.warn("Unknown Relationshiptype");
263 success.setValue(false);
264 }
265 taxonStore.add(toTaxon);
266 }
267 }else{
268 if (toTaxon == null){
269 logger.warn("toTaxon (" +
270 }
271 if (fromTaxon == null){
272 logger.warn("fromTaxon (" +
273 }
274 success.setValue(false);
275 }
276
277 } catch (UnknownCdmTypeException e) {
278
279 logger.warn("relationshipType " + strRelType + " not yet implemented");
280 success.setValue(false);
281 }
282 return;
283 }
284
285 private void makeTaxonRelationship(TcsXmlImportState state, TaxonRelationshipType relType, TaxonBase fromTaxon, Taxon taxonTo, ReferenceBase citation, String microReference, ResultWrapper<Boolean> success){
286 TaxonRelationshipType taxRelType = (TaxonRelationshipType)relType;
287 if (! (fromTaxon instanceof Taxon )){
288 logger.warn("TaxonBase fromTaxon " +
289 success.setValue(false);
290 }else{
291 Taxon taxonFrom = (Taxon)fromTaxon;
292 if (relType.equals(TaxonRelationshipType.TAXONOMICALLY_INCLUDED_IN())){
293 makeTaxonomicallyIncluded(state, taxonTo, taxonFrom, citation, microReference);
294 }
295 taxonFrom.addTaxonRelation(taxonTo, taxRelType, citation, microReference);
296 }
297 }
298
299 private boolean makeTaxonomicallyIncluded(TcsXmlImportState state, Taxon toTaxon, Taxon fromTaxon, ReferenceBase citation, String microCitation){
300 ReferenceBase sec = toTaxon.getSec();
301 TaxonomicTree tree = state.getTree(sec);
302 if (tree == null){
303 tree = makeTree(state, sec);
304 }
305 TaxonNode childNode = tree.addParentChild(toTaxon, fromTaxon, citation, microCitation);
306 return (childNode != null);
307 }
308
309
310 private TaxonBase getToTaxon(Element elTaxonRelationship, MapWrapper<TaxonBase> map, boolean isSynonym, ResultWrapper<Boolean> success){
311 TaxonBase result = null;
312 if (elTaxonRelationship == null || map == null){
313 success.setValue(false);
314 }else{
315 String childName = "ToTaxonConcept";
316 boolean obligatory = true;
317 Element elToTaxonConcept = XmlHelp.getSingleChildElement(success, elTaxonRelationship, childName, elTaxonRelationship.getNamespace(), obligatory);
318
319 String linkType = elToTaxonConcept.getAttributeValue("linkType");
320 if (linkType == null || linkType.equals("local")){
321 String ref = elToTaxonConcept.getAttributeValue("ref");
322 if (ref != null){
323 result = map.get(ref);
324 }else{
325 String title = elToTaxonConcept.getTextNormalize();
326
327 TaxonNameBase<?,?> taxonName = NonViralName.NewInstance(null);
328 taxonName.setTitleCache(title, true);
329 logger.warn("Free text related taxon seems to be bug in TCS");
330 if (isSynonym){
331 result = Synonym.NewInstance(taxonName, TcsXmlTaxonImport.unknownSec());
332 }else{
333 result = Taxon.NewInstance(taxonName, TcsXmlTaxonImport.unknownSec());
334 }
335 result.setTitleCache(title, true);
336 }
337 }else{
338 logger.warn("External link types for synonym not yet implemented");
339 }
340 }
341 return result;
342 }
343
344
345
346
347
348 private boolean relationExists(Taxon taxonTo, Synonym synonym, SynonymRelationshipType synRelType){
349 if (synonym == null){
350 return false;
351 }
352 if (synonym.getRelationType(taxonTo).size() > 0){
353 Set<SynonymRelationshipType> relTypeList = synonym.getRelationType(taxonTo);
354 if (relTypeList.contains(synRelType)){
355 return true;
356 }else{
357 logger.warn("Taxon-Synonym pair has 2 different SynonymRelationships. This is against the rules");
358 return false;
359 }
360 }else{
361 return false;
362 }
363 }
364
365 private boolean makeHomotypicSynonymRelations(Taxon aboutTaxon){
366 TaxonNameBase<?,?> aboutName = aboutTaxon.getName();
367 if (aboutName != null){
368 Set<TaxonNameBase> typifiedNames = aboutName.getHomotypicalGroup().getTypifiedNames();
369 for (TaxonNameBase<?,?> typifiedName : typifiedNames){
370
371 if (typifiedName.equals(aboutName)){
372 continue;
373 }
374 Set<Synonym> syns = typifiedName.getSynonyms();
375 for(Synonym syn:syns){
376 aboutTaxon.addSynonym(syn, SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF());
377 }
378 }
379 }
380 return true;
381 }
382
383
384
385
386 protected boolean isIgnore(TcsXmlImportState state){
387 return ! state.getConfig().isDoRelTaxa();
388 }
389
390 }