Project

General

Profile

Download (27.9 KB) Statistics
| Branch: | Revision:
1
/**
2
* Copyright (C) 2007 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9

    
10
package eu.etaxonomy.cdm.io.berlinModel.in;
11

    
12
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.TAX_REL_IS_HETEROTYPIC_SYNONYM_OF;
13
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.TAX_REL_IS_HOMOTYPIC_SYNONYM_OF;
14
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.TAX_REL_IS_INCLUDED_IN;
15
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.TAX_REL_IS_MISAPPLIED_NAME_OF;
16
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.TAX_REL_IS_PARTIAL_HETEROTYPIC_SYNONYM_OF;
17
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.TAX_REL_IS_PARTIAL_HOMOTYPIC_SYNONYM_OF;
18
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.TAX_REL_IS_PARTIAL_SYN_OF;
19
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.TAX_REL_IS_PROPARTE_HETEROTYPIC_SYNONYM_OF;
20
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.TAX_REL_IS_PROPARTE_HOMOTYPIC_SYNONYM_OF;
21
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.TAX_REL_IS_PROPARTE_SYN_OF;
22
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.TAX_REL_IS_SYNONYM_OF;
23

    
24
import java.sql.ResultSet;
25
import java.sql.SQLException;
26
import java.util.HashMap;
27
import java.util.HashSet;
28
import java.util.Map;
29
import java.util.Set;
30
import java.util.UUID;
31

    
32
import org.apache.commons.lang.StringUtils;
33
import org.apache.log4j.Logger;
34
import org.springframework.stereotype.Component;
35
import org.springframework.transaction.TransactionStatus;
36

    
37
import eu.etaxonomy.cdm.common.ResultWrapper;
38
import eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer;
39
import eu.etaxonomy.cdm.io.berlinModel.in.validation.BerlinModelTaxonRelationImportValidator;
40
import eu.etaxonomy.cdm.io.common.IOValidator;
41
import eu.etaxonomy.cdm.io.common.ResultSetPartitioner;
42
import eu.etaxonomy.cdm.io.common.Source;
43
import eu.etaxonomy.cdm.model.common.AnnotatableEntity;
44
import eu.etaxonomy.cdm.model.common.CdmBase;
45
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
46
import eu.etaxonomy.cdm.model.reference.Reference;
47
import eu.etaxonomy.cdm.model.taxon.Classification;
48
import eu.etaxonomy.cdm.model.taxon.Synonym;
49
import eu.etaxonomy.cdm.model.taxon.SynonymType;
50
import eu.etaxonomy.cdm.model.taxon.Taxon;
51
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
52
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
53
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
54
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
55
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
56

    
57
/**
58
 * @author a.mueller
59
 * @since 20.03.2008
60
 */
61
@Component
62
public class BerlinModelTaxonRelationImport  extends BerlinModelImportBase  {
63
    private static final long serialVersionUID = -7234926279240842557L;
64

    
65
    private static final Logger logger = Logger.getLogger(BerlinModelTaxonRelationImport.class);
66

    
67
	public static final String TREE_NAMESPACE = "PTRefFk";
68

    
69
	private static int modCount = 30000;
70
	private static final String pluralString = "taxon relations";
71
	private static final String dbTableName = "RelPTaxon";
72

    
73

    
74
	public BerlinModelTaxonRelationImport(){
75
		super(dbTableName, pluralString);
76
	}
77

    
78
	/**
79
	 * Creates a classification for each PTaxon reference which belongs to a taxon that is
80
	 * included at least in one <i>taxonomically included</i> relationship.
81
	 *
82
	 * @param state
83
	 * @throws SQLException
84
	 */
85
	private void makeClassifications(BerlinModelImportState state) throws SQLException{
86
		logger.info("start make classification ...");
87

    
88
		Set<String> idSet = getTreeReferenceIdSet(state);
89

    
90
		//reference map
91
		String nameSpace = BerlinModelReferenceImport.REFERENCE_NAMESPACE;
92
		Class<?> cdmClass = Reference.class;
93
		@SuppressWarnings("unchecked")
94
        Map<String, Reference> refMap = (Map<String, Reference>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
95

    
96
		String classificationName = "Classification - No Name";
97

    
98
		ResultSet rs = state.getConfig().getSource().getResultSet(getClassificationQuery(state)) ;
99
		int i = 0;
100
		//for each reference
101
		try {
102
			//TODO handle case useSingleClassification = true && sourceSecId = null, which returns no record
103
			boolean isFirst = true;
104
		    while (rs.next()){
105

    
106
				try {
107
					if ((i++ % modCount) == 0 && i!= 1 ){ logger.info("RelPTaxa handled: " + (i-1));}
108

    
109
					Integer ptRefFkInt = nullSafeInt(rs,"PTRefFk");
110
					String ptRefFk= String.valueOf(ptRefFkInt);
111
					Reference ref = refMap.get(ptRefFk);
112

    
113
					String refCache = rs.getString("RefCache");
114
					if (isNotBlank(refCache)){
115
						classificationName = refCache;
116
					}
117
					if (ref != null && StringUtils.isNotBlank(ref.getTitleCache())){
118
						classificationName = ref.getTitleCache();
119
					}
120
					if (isFirst && isNotBlank(state.getConfig().getClassificationName())){
121
					    classificationName = state.getConfig().getClassificationName();
122
					}
123
					Classification tree = Classification.NewInstance(classificationName);
124
					tree.setReference(ref);
125
					if (i == 1 && state.getConfig().getClassificationUuid() != null){
126
						tree.setUuid(state.getConfig().getClassificationUuid());
127
					}
128
					IdentifiableSource identifiableSource = IdentifiableSource.NewDataImportInstance(ptRefFk, TREE_NAMESPACE);
129
					tree.addSource(identifiableSource);
130

    
131
					getClassificationService().save(tree);
132
					state.putClassificationUuidInt(ptRefFkInt, tree);
133
					isFirst = false;
134
				} catch (Exception e) {
135
					logger.error("Error in BerlinModleTaxonRelationImport.makeClassifications: " + e.getMessage());
136
					e.printStackTrace();
137
				}
138
			}
139
		} catch (SQLException e) {
140
			logger.error("Error in BerlinModleTaxonRelationImport.makeClassifications: " + e.getMessage());
141
			throw e;
142
		}
143
		logger.info("end make classification ...");
144

    
145
		return;
146
	}
147

    
148
	/**
149
	 * @return
150
	 * @throws SQLException
151
	 */
152
	private Set<String> getTreeReferenceIdSet(BerlinModelImportState state) throws SQLException {
153
		Source source = state.getConfig().getSource();
154
		Set<String> result = new HashSet<String>();
155
		ResultSet rs = source.getResultSet(getClassificationQuery(state)) ;
156
		while (rs.next()){
157
			Object id = rs.getObject("PTRefFk");
158
			result.add(String.valueOf(id));
159
		}
160
		return result;
161
	}
162

    
163
	private String getClassificationQuery(BerlinModelImportState state) {
164
		boolean includeAllClassifications = state.getConfig().isIncludeAllNonMisappliedRelatedClassifications();
165
		String strQuerySelect = "SELECT PTaxon.PTRefFk, r.RefCache ";
166
		String strQueryFrom = " FROM RelPTaxon " +
167
							" INNER JOIN PTaxon AS PTaxon ON RelPTaxon.PTNameFk2 = PTaxon.PTNameFk AND RelPTaxon.PTRefFk2 = PTaxon.PTRefFk " +
168
							" INNER JOIN Reference r ON PTaxon.PTRefFk = r.RefId ";
169
		String strQueryWhere = " WHERE (RelPTaxon.RelQualifierFk = 1) ";
170
		if (includeAllClassifications){
171
			strQueryWhere = " WHERE (RelPTaxon.RelQualifierFk <> 3) ";
172
		}else{
173
			if (state.getConfig().isUseSingleClassification()){
174
				if (state.getConfig().getSourceSecId()!= null){
175
					strQueryWhere += " AND PTaxon.PTRefFk = " + state.getConfig().getSourceSecId() +  " ";
176
				}else{
177
					strQueryWhere += " AND (1=0) ";
178
				}
179
			}
180
		}
181

    
182
		String strQueryGroupBy = " GROUP BY PTaxon.PTRefFk, r.RefCache ";
183
		String strQuery = strQuerySelect + " " + strQueryFrom + " " + strQueryWhere + " " + strQueryGroupBy;
184

    
185

    
186
		if (includeAllClassifications){
187
			//add otherdirection
188
			strQuerySelect = "SELECT PTaxon.PTRefFk, r.RefCache ";
189
			strQueryFrom = " FROM RelPTaxon rel " +
190
								" INNER JOIN PTaxon AS PTaxon ON rel.PTNameFk1 = PTaxon.PTNameFk AND rel.PTRefFk1 = PTaxon.PTRefFk " +
191
								" INNER JOIN Reference r ON PTaxon.PTRefFk = r.RefId ";
192
			strQueryWhere =" WHERE (rel.RelQualifierFk <> 3) ";
193
			String strAllQuery =  strQuerySelect + " " + strQueryFrom + " " + strQueryWhere + " " + strQueryGroupBy;
194
			strQuery = strQuery + " UNION " + strAllQuery;
195
		}
196

    
197

    
198

    
199
		boolean includeFlatClassifications = state.getConfig().isIncludeFlatClassifications();
200
		//concepts with
201
		if (includeFlatClassifications){
202
			String strFlatQuery =
203
					" SELECT pt.PTRefFk AS secRefFk, r.RefCache AS secRef " +
204
					" FROM PTaxon AS pt LEFT OUTER JOIN " +
205
					          " Reference r ON pt.PTRefFk = r.RefId LEFT OUTER JOIN " +
206
					          " RelPTaxon rel1 ON pt.PTNameFk = rel1.PTNameFk2 AND pt.PTRefFk = rel1.PTRefFk2 LEFT OUTER JOIN " +
207
					          " RelPTaxon AS rel2 ON pt.PTNameFk = rel2.PTNameFk1 AND pt.PTRefFk = rel2.PTRefFk1 " +
208
					" WHERE (rel2.RelQualifierFk IS NULL) AND (rel1.RelQualifierFk IS NULL) " +
209
					" GROUP BY pt.PTRefFk, r.RefCache "
210
					;
211

    
212
			strQuery = strQuery + " UNION " + strFlatQuery;
213
		}
214

    
215

    
216

    
217
		if (state.getConfig().getClassificationQuery() != null){
218
			strQuery = state.getConfig().getClassificationQuery();
219
		}
220
		return strQuery;
221
	}
222

    
223
	@Override
224
	protected String getRecordQuery(BerlinModelImportConfigurator config) {
225
		String strQuery =
226
			" SELECT RelPTaxon.*, fromTaxon.RIdentifier as taxon1Id, toTaxon.RIdentifier as taxon2Id, toTaxon.PTRefFk as treeRefFk, fromTaxon.PTRefFk as fromRefFk, q.is_concept_relation " +
227
			" FROM PTaxon as fromTaxon " +
228
              	" INNER JOIN RelPTaxon ON fromTaxon.PTNameFk = relPTaxon.PTNameFk1 AND fromTaxon.PTRefFk = relPTaxon.PTRefFk1 " +
229
              	" INNER JOIN PTaxon AS toTaxon ON RelPTaxon.PTNameFk2 = ToTaxon.PTNameFk AND RelPTaxon.PTRefFk2 = ToTaxon.PTRefFk " +
230
              	" INNER JOIN RelPTQualifier q ON q.RelPTQualifierId = RelPTaxon.RelQualifierFk " +
231
            " WHERE RelPTaxon.RelPTaxonId IN ("+ID_LIST_TOKEN+") " +
232
            " ORDER BY RelPTaxon.RelPTaxonId ";
233
		return strQuery;
234
	}
235

    
236
	@Override
237
	public boolean doPartition(ResultSetPartitioner partitioner, BerlinModelImportState state) {
238
		boolean success = true ;
239
		Set<TaxonBase> taxaToSave = new HashSet<>();
240
		Map<String, TaxonBase> taxonMap = partitioner.getObjectMap(BerlinModelTaxonImport.NAMESPACE);
241
		Map<Integer, Classification> classificationMap = new HashMap<>();
242
		Map<String, Reference> refMap = partitioner.getObjectMap(BerlinModelReferenceImport.REFERENCE_NAMESPACE);
243

    
244
		ResultSet rs = partitioner.getResultSet();
245

    
246
		try{
247
			int i = 0;
248
			//for each reference
249
			while (rs.next()){
250

    
251
				if ((i++ % modCount) == 0 && i!= 1 ){ logger.info("RelPTaxa handled: " + (i-1));}
252

    
253
				int relPTaxonId = rs.getInt("RelPTaxonId");
254
				Integer taxon1Id = nullSafeInt(rs, "taxon1Id");
255
				Integer taxon2Id = nullSafeInt(rs, "taxon2Id");
256
				int relQualifierFk = -1;
257
				try {
258
					Integer relRefFk = nullSafeInt(rs,"relRefFk");
259
					int treeRefFk = rs.getInt("treeRefFk");
260
					int fromRefFk = rs.getInt("fromRefFk");
261

    
262
					relQualifierFk = rs.getInt("relQualifierFk");
263
					String notes = rs.getString("notes");
264
					boolean isConceptRelationship = rs.getBoolean("is_concept_relation");
265

    
266
					TaxonBase<?> taxon1 = taxonMap.get(String.valueOf(taxon1Id));
267
					TaxonBase<?> taxon2 = taxonMap.get(String.valueOf(taxon2Id));
268

    
269
					String refFk = String.valueOf(relRefFk);
270
					Reference citation = refMap.get(refFk);
271

    
272
					String microcitation = null; //does not exist in RelPTaxon
273

    
274
					if (taxon2 != null && taxon1 != null){
275
						if (!(taxon2 instanceof Taxon)){
276
							logger.error("ToTaxon (ID = " + taxon2.getId()+ ", RIdentifier = " + taxon2Id + ") can't be casted to Taxon. RelPTaxon: " + relPTaxonId );
277
							success = false;
278
							continue;
279
						}
280
						AnnotatableEntity taxonRelationship = null;
281
						Taxon toTaxon = (Taxon)taxon2;
282
						if (isTaxonRelationship(relQualifierFk)){
283
							if (!(taxon1 instanceof Taxon)){
284
								logger.error("TaxonBase (ID = " + taxon1.getId()+ ", RIdentifier = " + taxon1Id + ") for TaxonRelation ("+relPTaxonId+") can't be casted to Taxon");
285
								success = false;
286
								continue;
287
							}
288
							Taxon fromTaxon = (Taxon)taxon1;
289
							if (relQualifierFk == TAX_REL_IS_INCLUDED_IN){
290
								taxonRelationship = makeTaxonomicallyIncluded(state, classificationMap, treeRefFk, fromTaxon, toTaxon, citation, microcitation);
291
							}else if (relQualifierFk == TAX_REL_IS_MISAPPLIED_NAME_OF){
292
								 taxonRelationship = toTaxon.addMisappliedName(fromTaxon, citation, microcitation);
293
                            }else if (relQualifierFk == TAX_REL_IS_PROPARTE_SYN_OF ||
294
                                    //TODO homo/hetero
295
                                    relQualifierFk == TAX_REL_IS_PROPARTE_HOMOTYPIC_SYNONYM_OF ||
296
                                    relQualifierFk == TAX_REL_IS_PROPARTE_HETEROTYPIC_SYNONYM_OF ){
297
                                toTaxon.addProparteSynonym(fromTaxon, citation, microcitation);
298
                            }else if(relQualifierFk == TAX_REL_IS_PARTIAL_SYN_OF ||
299
                                    //TODO homo/hetero
300
                                    relQualifierFk == TAX_REL_IS_PARTIAL_HOMOTYPIC_SYNONYM_OF ||
301
                                    relQualifierFk == TAX_REL_IS_PARTIAL_HETEROTYPIC_SYNONYM_OF ){
302
                                toTaxon.addPartialSynonym(fromTaxon, citation, microcitation);
303
                            }else{
304
								handleAllRelatedTaxa(state, fromTaxon, classificationMap, fromRefFk);
305
								handleAllRelatedTaxa(state, toTaxon, classificationMap, treeRefFk);
306
								logger.warn("Unhandled taxon relationship: RelId:" + relPTaxonId + "; QualifierId: " + relQualifierFk);
307
							}
308
						}else if (isSynonymRelationship(relQualifierFk)){
309
							if (!(taxon1 instanceof Synonym)){
310
								logger.warn("Validated: Taxon (ID = " + taxon1.getId()+ ", RIdentifier = " + taxon1Id + ") can't be casted to Synonym");
311
								success = false;
312
								continue;
313
							}
314
							handleAllRelatedTaxa(state, toTaxon, classificationMap, treeRefFk);
315
							Synonym synonym = (Synonym)taxon1;
316
							if (synonym.getAcceptedTaxon()!= null){
317
							    logger.warn("RelID: " + relPTaxonId + ". Synonym ("+taxon1Id +") already has an accepted taxon. Create clone.");
318
							    synonym = (Synonym)synonym.clone();
319
							}
320
							makeSynRel(state, relQualifierFk, toTaxon, synonym, citation, microcitation);
321

    
322
							if (relQualifierFk == TAX_REL_IS_SYNONYM_OF ||
323
									relQualifierFk == TAX_REL_IS_HOMOTYPIC_SYNONYM_OF ||
324
									relQualifierFk == TAX_REL_IS_HETEROTYPIC_SYNONYM_OF){
325
							}else{
326
								success = false;
327
								logger.warn("Synonym relationship type not yet implemented: " + relQualifierFk);
328
							}
329
						}else if (isConceptRelationship){
330
							ResultWrapper<Boolean> isInverse = ResultWrapper.NewInstance(false);
331
							ResultWrapper<Boolean> isDoubtful = ResultWrapper.NewInstance(false);
332
							try {
333
								TaxonRelationshipType relType = BerlinModelTransformer.taxonRelId2TaxonRelType(relQualifierFk, isInverse, isDoubtful);
334

    
335
								if (! (taxon1 instanceof Taxon)){
336
									success = false;
337
									logger.error("TaxonBase (ID = " + taxon1.getId()+ ", RIdentifier = " + taxon1Id + ") can't be casted to Taxon");
338
								}else{
339
									Taxon fromTaxon = (Taxon)taxon1;
340
									if (isInverse.getValue() == true){
341
										Taxon tmp = fromTaxon;
342
										fromTaxon = toTaxon;
343
										toTaxon = tmp;
344
									}
345
									taxonRelationship = fromTaxon.addTaxonRelation(toTaxon, relType, citation, microcitation);
346
									handleAllRelatedTaxa(state, toTaxon, classificationMap, treeRefFk);
347
									handleAllRelatedTaxa(state, fromTaxon, classificationMap, fromRefFk);
348
									if (isDoubtful.getValue() == true){
349
										((TaxonRelationship)taxonRelationship).setDoubtful(true);
350
									}
351
								}
352
							} catch (UnknownCdmTypeException e) {
353
								logger.warn("TaxonRelationShipType " + relQualifierFk + " (conceptRelationship) not yet implemented");
354
								 success = false;
355
							}
356
						}else {
357
							logger.warn("TaxonRelationShipType " + relQualifierFk + " not yet implemented: RelPTaxonId = " + relPTaxonId );
358
							success = false;
359
						}
360

    
361
						if (taxonRelationship != null){
362
						    doNotes(taxonRelationship, notes);
363
						}else if (isNotBlank(notes)){
364
						    logger.warn("Notes for synonym relationship or unknown taxon relationship not handled. RelID: " + relPTaxonId + ". Note: " + notes);
365
						}
366
						taxaToSave.add(taxon2);
367

    
368
						//TODO
369
						//etc.
370
					}else{
371
						if (taxon2 != null && taxon1 == null){
372
							logger.warn("First taxon ("+taxon1Id+") for RelPTaxon " + relPTaxonId + " does not exist in store. RelType: " + relQualifierFk);
373
						}else if (taxon2 == null && taxon1 != null){
374
							logger.warn("Second taxon ("+taxon2Id +") for RelPTaxon " + relPTaxonId + " does not exist in store. RelType: " + relQualifierFk);
375
						}else{
376
							logger.warn("Both taxa ("+taxon1Id+","+taxon2Id +") for RelPTaxon " + relPTaxonId + " do not exist in store. RelType: " + relQualifierFk);
377
						}
378

    
379
						success = false;
380
					}
381
				} catch (Exception e) {
382
					logger.error("Exception occurred when trying to handle taxon relationship " + relPTaxonId + " relQualifierFK " + relQualifierFk + " (" + taxon1Id + ","+ taxon2Id + "): " + e.getMessage());
383
					e.printStackTrace();
384
				}
385
			}
386
		}catch(SQLException e){
387
			throw new RuntimeException(e);
388
		}
389
		logger.info("Taxa to save: " + taxaToSave.size());
390
		partitioner.startDoSave();
391
		getTaxonService().saveOrUpdate(taxaToSave);
392
		classificationMap = null;
393
		taxaToSave = null;
394

    
395
		return success;
396
	}
397

    
398

    
399
	private void handleAllRelatedTaxa(BerlinModelImportState state, Taxon taxon, Map<Integer, Classification> classificationMap, Integer secRefFk) {
400
		if (taxon.getTaxonNodes().size() > 0){
401
			return;
402
		}else{
403
			Classification classification = getClassificationTree(state, classificationMap, secRefFk);
404
			classification.addChildTaxon(taxon, null, null);
405
		}
406
	}
407

    
408
	@Override
409
	protected void doInvoke(BerlinModelImportState state){
410
		try {
411
			makeClassifications(state);
412
			super.doInvoke(state);
413
			makeFlatClassificationTaxa(state);
414
			return;
415
		} catch (SQLException e) {
416
			throw new RuntimeException(e);
417
		}
418

    
419
	}
420

    
421

    
422
	private void makeFlatClassificationTaxa(BerlinModelImportState state) {
423
		//Note: this part still does not use partitions
424
		logger.info("Flat classifications start");
425
		TransactionStatus txStatus = startTransaction();
426
		if (! state.getConfig().isIncludeFlatClassifications()){
427
			return;
428
		}
429
		String sql = " SELECT pt.PTRefFk AS secRefFk, pt.RIdentifier " +
430
						" FROM PTaxon AS pt " +
431
							" LEFT OUTER JOIN RelPTaxon ON pt.PTNameFk = RelPTaxon.PTNameFk2 AND pt.PTRefFk = RelPTaxon.PTRefFk2 " +
432
							"  LEFT OUTER JOIN RelPTaxon AS RelPTaxon_1 ON pt.PTNameFk = RelPTaxon_1.PTNameFk1 AND pt.PTRefFk = RelPTaxon_1.PTRefFk1 " +
433
						" WHERE (RelPTaxon_1.RelQualifierFk IS NULL) AND (dbo.RelPTaxon.RelQualifierFk IS NULL) " +
434
						" ORDER BY pt.PTRefFk "	;
435
		ResultSet rs = state.getConfig().getSource().getResultSet(sql);
436
		Map<Object, Map<String, ? extends CdmBase>> maps = getRelatedObjectsForFlatPartition(rs);
437

    
438
		Map<String, TaxonBase> taxonMap = (Map<String, TaxonBase>) maps.get(BerlinModelTaxonImport.NAMESPACE);
439
		Map<Integer, Classification> classificationMap = new HashMap<>();
440

    
441
		rs = state.getConfig().getSource().getResultSet(sql);
442
		try {
443
			while (rs.next()){
444
				Integer treeRefFk = rs.getInt("secRefFk");
445
				String taxonId = rs.getString("RIdentifier");
446
				Classification classification = getClassificationTree(state, classificationMap, treeRefFk);
447
				TaxonBase<?> taxon = taxonMap.get(taxonId);
448
				if (taxon == null){
449
					String message = "TaxonBase for taxon id (%s) not found in taxonMap";
450
					logger.warn(String.format(message, taxonId, taxonId));
451
				}else if (taxon.isInstanceOf(Taxon.class)){
452
					classification.addChildTaxon(CdmBase.deproxy(taxon, Taxon.class), null, null);
453
				}else{
454
					String message = "TaxonBase for taxon is not of class Taxon but %s (RIdentifier %s)";
455
					logger.warn(String.format(message, taxon.getClass(), taxonId));
456
				}
457
			}
458
		} catch (SQLException e) {
459
			e.printStackTrace();
460
		}
461
		commitTransaction(txStatus);
462
		logger.info("Flat classifications end");
463

    
464
	}
465

    
466
	@Override
467
	protected String getIdQuery(BerlinModelImportState state) {
468
		if (state.getConfig().getRelTaxaIdQuery() != null){
469
			return state.getConfig().getRelTaxaIdQuery();
470
		}else{
471
			return super.getIdQuery(state);
472
		}
473
	}
474

    
475
	@Override
476
	public Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForPartition(ResultSet rs, BerlinModelImportState state) {
477
		String nameSpace;
478
		Class<?> cdmClass;
479
		Set<String> idSet;
480
		Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<>();
481

    
482
		try{
483
			Set<String> taxonIdSet = new HashSet<>();
484
			Set<String> referenceIdSet = new HashSet<>();
485
//			Set<String> classificationIdSet = new HashSet<>();
486
			while (rs.next()){
487
				handleForeignKey(rs, taxonIdSet, "taxon1Id");
488
				handleForeignKey(rs, taxonIdSet, "taxon2Id");
489
//				handleForeignKey(rs, classificationIdSet, "treeRefFk");
490
				handleForeignKey(rs, referenceIdSet, "RelRefFk");
491
	}
492

    
493
			//taxon map
494
			nameSpace = BerlinModelTaxonImport.NAMESPACE;
495
			cdmClass = TaxonBase.class;
496
			idSet = taxonIdSet;
497
			Map<String, TaxonBase> taxonMap = (Map<String, TaxonBase>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
498
			result.put(nameSpace, taxonMap);
499

    
500
//			//tree map
501
//			nameSpace = "Classification";
502
//			cdmClass = Classification.class;
503
//			idSet = classificationIdSet;
504
//			Map<String, Classification> treeMap = (Map<String, Classification>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
505
//			result.put(cdmClass, treeMap);
506
//			Set<UUID> treeUuidSet = state
507
//			getClassificationService().find(uuidSet);
508
//
509
			//reference map
510
			nameSpace = BerlinModelReferenceImport.REFERENCE_NAMESPACE;
511
			cdmClass = Reference.class;
512
			idSet = referenceIdSet;
513
			Map<String, Reference> referenceMap = (Map<String, Reference>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
514
			result.put(nameSpace, referenceMap);
515

    
516
		} catch (SQLException e) {
517
			throw new RuntimeException(e);
518
		}
519
		return result;
520
	}
521

    
522

    
523
	private Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForFlatPartition( ResultSet rs) {
524
		String nameSpace;
525
		Class cdmClass;
526
		Set<String> idSet;
527
		Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<>();
528

    
529
		try{
530
			Set<String> taxonIdSet = new HashSet<>();
531
			Set<String> referenceIdSet = new HashSet<>();
532
//			Set<String> classificationIdSet = new HashSet<>();
533
			while (rs.next()){
534
				handleForeignKey(rs, taxonIdSet, "RIdentifier");
535
//				handleForeignKey(rs, classificationIdSet, "treeRefFk");
536
			}
537

    
538
			//taxon map
539
			nameSpace = BerlinModelTaxonImport.NAMESPACE;
540
			cdmClass = TaxonBase.class;
541
			idSet = taxonIdSet;
542
			Map<String, TaxonBase> taxonMap = (Map<String, TaxonBase>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
543
			result.put(nameSpace, taxonMap);
544

    
545
//			//tree map
546
//			nameSpace = "Classification";
547
//			cdmClass = Classification.class;
548
//			idSet = classificationIdSet;
549
//			Map<String, Classification> treeMap = (Map<String, Classification>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
550
//			result.put(cdmClass, treeMap);
551
//			Set<UUID> treeUuidSet = state
552
//			getClassificationService().find(uuidSet);
553
//
554

    
555
		} catch (SQLException e) {
556
			throw new RuntimeException(e);
557
		}
558
		return result;
559
	}
560

    
561

    
562
	private void makeSynRel (BerlinModelImportState state, int relQualifierFk, Taxon toTaxon, Synonym synonym, Reference citation, String microcitation){
563
		if (state.getConfig().isWarnForDifferingSynonymReference() && citation != null && !citation.equals(synonym.getSec())){
564
		    logger.warn("A synonym relationship citation is given and differs from synonym secundum. This can not be handled in CDM");
565
		}
566
		if (isNotBlank(microcitation)  && !microcitation.equals(synonym.getSecMicroReference())){
567
            logger.warn("A synonym relationship microcitation is given and differs from synonym secundum micro reference. This can not be handled in CDM");
568
        }
569
	    if (relQualifierFk == TAX_REL_IS_HOMOTYPIC_SYNONYM_OF ||
570
				relQualifierFk == TAX_REL_IS_PROPARTE_HOMOTYPIC_SYNONYM_OF ||
571
				relQualifierFk == TAX_REL_IS_PARTIAL_HOMOTYPIC_SYNONYM_OF){
572
			toTaxon.addHomotypicSynonym(synonym);
573
		}else if (relQualifierFk == TAX_REL_IS_HETEROTYPIC_SYNONYM_OF ||
574
				relQualifierFk == TAX_REL_IS_PROPARTE_HETEROTYPIC_SYNONYM_OF ||
575
				relQualifierFk == TAX_REL_IS_PARTIAL_HETEROTYPIC_SYNONYM_OF){
576
			toTaxon.addSynonym(synonym, SynonymType.HETEROTYPIC_SYNONYM_OF());
577
		}else if (relQualifierFk == TAX_REL_IS_SYNONYM_OF ||
578
				relQualifierFk == TAX_REL_IS_PROPARTE_SYN_OF ||
579
				relQualifierFk == TAX_REL_IS_PARTIAL_SYN_OF){
580
			toTaxon.addSynonym(synonym, SynonymType.SYNONYM_OF());
581
		}else{
582
			logger.warn("SynonymyRelationShipType could not be defined for relQualifierFk " + relQualifierFk + ". 'Unknown'-Type taken instead.");
583
			toTaxon.addSynonym(synonym, SynonymType.SYNONYM_OF());
584
		}
585
		return;
586

    
587
	}
588

    
589
	private  boolean isSynonymRelationship(int relQualifierFk){
590
		if (relQualifierFk == TAX_REL_IS_SYNONYM_OF ||
591
			relQualifierFk == TAX_REL_IS_HOMOTYPIC_SYNONYM_OF ||
592
			relQualifierFk == TAX_REL_IS_HETEROTYPIC_SYNONYM_OF ||
593
			relQualifierFk == TAX_REL_IS_PROPARTE_SYN_OF ||
594
			relQualifierFk == TAX_REL_IS_PARTIAL_SYN_OF ||
595
			relQualifierFk == TAX_REL_IS_PROPARTE_HOMOTYPIC_SYNONYM_OF ||
596
			relQualifierFk == TAX_REL_IS_PROPARTE_HETEROTYPIC_SYNONYM_OF ||
597
			relQualifierFk == TAX_REL_IS_PARTIAL_HOMOTYPIC_SYNONYM_OF ||
598
			relQualifierFk == TAX_REL_IS_PARTIAL_HETEROTYPIC_SYNONYM_OF
599
		){
600
			return true;
601
		}else{
602
			return false;
603
		}
604
	}
605

    
606
	private  boolean isTaxonRelationship(int relQualifierFk){
607
		if (relQualifierFk == TAX_REL_IS_INCLUDED_IN ||
608
				relQualifierFk == TAX_REL_IS_MISAPPLIED_NAME_OF){
609
			return true;
610
		}else if (relQualifierFk == TAX_REL_IS_PROPARTE_SYN_OF ||
611
	                relQualifierFk == TAX_REL_IS_PARTIAL_SYN_OF ||
612
	                relQualifierFk == TAX_REL_IS_PROPARTE_HOMOTYPIC_SYNONYM_OF ||
613
	                relQualifierFk == TAX_REL_IS_PROPARTE_HETEROTYPIC_SYNONYM_OF ||
614
	                relQualifierFk == TAX_REL_IS_PARTIAL_HOMOTYPIC_SYNONYM_OF ||
615
	                relQualifierFk == TAX_REL_IS_PARTIAL_HETEROTYPIC_SYNONYM_OF
616
                    ){
617
	            return true;
618

    
619
		}else{
620
			return false;
621
		}
622
	}
623

    
624
	private TaxonNode makeTaxonomicallyIncluded(BerlinModelImportState state, Map<Integer, Classification> classificationMap, int treeRefFk, Taxon child, Taxon parent, Reference citation, String microCitation){
625
		Classification tree = getClassificationTree(state, classificationMap, treeRefFk);
626
		return tree.addParentChild(parent, child, citation, microCitation);
627
	}
628

    
629
	private Classification getClassificationTree(BerlinModelImportState state, Map<Integer, Classification> classificationMap, int treeRefFk) {
630
		if (state.getConfig().isUseSingleClassification()){
631
			if (state.getConfig().getSourceSecId() != null){
632
				treeRefFk = (Integer)state.getConfig().getSourceSecId();
633
			}else{
634
				treeRefFk = 1;
635
			}
636

    
637
		}
638
		Classification tree = classificationMap.get(treeRefFk);
639
		if (tree == null){
640
			UUID treeUuid = state.getTreeUuidByIntTreeKey(treeRefFk);
641
			if (treeUuid == null){
642
				throw new IllegalStateException("treeUUID does not exist in state for " + treeRefFk );
643
			}
644
			tree = getClassificationService().find(treeUuid);
645
			classificationMap.put(treeRefFk, tree);
646
		}
647
		if (tree == null){
648
			throw new IllegalStateException("Tree for ToTaxon reference " + treeRefFk + " does not exist.");
649
		}
650
		return tree;
651
	}
652

    
653
	@Override
654
	protected boolean doCheck(BerlinModelImportState state){
655
		IOValidator<BerlinModelImportState> validator = new BerlinModelTaxonRelationImportValidator();
656
		return validator.validate(state);
657
	}
658

    
659
	@Override
660
	protected boolean isIgnore(BerlinModelImportState state){
661
		return ! state.getConfig().isDoRelTaxa();
662
	}
663

    
664

    
665
}
(18-18/22)