Project

General

Profile

Download (28.6 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 included at least in one
80
	 * <i>taxonomically included</i> relationship
81
	 * @param state
82
	 * @return
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
	/**
164
	 * @return
165
	 */
166
	private String getClassificationQuery(BerlinModelImportState state) {
167
		boolean includeAllClassifications = state.getConfig().isIncludeAllNonMisappliedRelatedClassifications();
168
		String strQuerySelect = "SELECT PTaxon.PTRefFk, r.RefCache ";
169
		String strQueryFrom = " FROM RelPTaxon " +
170
							" INNER JOIN PTaxon AS PTaxon ON RelPTaxon.PTNameFk2 = PTaxon.PTNameFk AND RelPTaxon.PTRefFk2 = PTaxon.PTRefFk " +
171
							" INNER JOIN Reference r ON PTaxon.PTRefFk = r.RefId ";
172
		String strQueryWhere = " WHERE (RelPTaxon.RelQualifierFk = 1) ";
173
		if (includeAllClassifications){
174
			strQueryWhere = " WHERE (RelPTaxon.RelQualifierFk <> 3) ";
175
		}else{
176
			if (state.getConfig().isUseSingleClassification()){
177
				if (state.getConfig().getSourceSecId()!= null){
178
					strQueryWhere += " AND PTaxon.PTRefFk = " + state.getConfig().getSourceSecId() +  " ";
179
				}else{
180
					strQueryWhere += " AND (1=0) ";
181
				}
182
			}
183
		}
184

    
185
		String strQueryGroupBy = " GROUP BY PTaxon.PTRefFk, r.RefCache ";
186
		String strQuery = strQuerySelect + " " + strQueryFrom + " " + strQueryWhere + " " + strQueryGroupBy;
187

    
188

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

    
200

    
201

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

    
215
			strQuery = strQuery + " UNION " + strFlatQuery;
216
		}
217

    
218

    
219

    
220
		if (state.getConfig().getClassificationQuery() != null){
221
			strQuery = state.getConfig().getClassificationQuery();
222
		}
223
		return strQuery;
224
	}
225

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

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

    
247
		ResultSet rs = partitioner.getResultSet();
248

    
249
		try{
250
			int i = 0;
251
			//for each reference
252
			while (rs.next()){
253

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

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

    
265
					relQualifierFk = rs.getInt("relQualifierFk");
266
					String notes = rs.getString("notes");
267
					boolean isConceptRelationship = rs.getBoolean("is_concept_relation");
268

    
269
					TaxonBase<?> taxon1 = taxonMap.get(String.valueOf(taxon1Id));
270
					TaxonBase<?> taxon2 = taxonMap.get(String.valueOf(taxon2Id));
271

    
272
					String refFk = String.valueOf(relRefFk);
273
					Reference citation = refMap.get(refFk);
274

    
275
					String microcitation = null; //does not exist in RelPTaxon
276

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

    
325
							if (relQualifierFk == TAX_REL_IS_SYNONYM_OF ||
326
									relQualifierFk == TAX_REL_IS_HOMOTYPIC_SYNONYM_OF ||
327
									relQualifierFk == TAX_REL_IS_HETEROTYPIC_SYNONYM_OF){
328
								//pro parte already set by taxon mapping
329
//							}else if (relQualifierFk == TAX_REL_IS_PROPARTE_SYN_OF ||
330
//									relQualifierFk == TAX_REL_IS_PROPARTE_HOMOTYPIC_SYNONYM_OF ||
331
//									relQualifierFk == TAX_REL_IS_PROPARTE_HETEROTYPIC_SYNONYM_OF ){
332
//									synonym.setProParte(true);
333
//							}else if(relQualifierFk == TAX_REL_IS_PARTIAL_SYN_OF ||
334
//									relQualifierFk == TAX_REL_IS_PARTIAL_HOMOTYPIC_SYNONYM_OF ||
335
//									relQualifierFk == TAX_REL_IS_PARTIAL_HETEROTYPIC_SYNONYM_OF ){
336
//							        synonym.setPartial(true);
337
							}else{
338
								success = false;
339
								logger.warn("Synonym relationship type not yet implemented: " + relQualifierFk);
340
							}
341
						}else if (isConceptRelationship){
342
							ResultWrapper<Boolean> isInverse = ResultWrapper.NewInstance(false);
343
							ResultWrapper<Boolean> isDoubtful = ResultWrapper.NewInstance(false);
344
							try {
345
								TaxonRelationshipType relType = BerlinModelTransformer.taxonRelId2TaxonRelType(relQualifierFk, isInverse, isDoubtful);
346

    
347
								if (! (taxon1 instanceof Taxon)){
348
									success = false;
349
									logger.error("TaxonBase (ID = " + taxon1.getId()+ ", RIdentifier = " + taxon1Id + ") can't be casted to Taxon");
350
								}else{
351
									Taxon fromTaxon = (Taxon)taxon1;
352
									if (isInverse.getValue() == true){
353
										Taxon tmp = fromTaxon;
354
										fromTaxon = toTaxon;
355
										toTaxon = tmp;
356
									}
357
									taxonRelationship = fromTaxon.addTaxonRelation(toTaxon, relType, citation, microcitation);
358
									handleAllRelatedTaxa(state, toTaxon, classificationMap, treeRefFk);
359
									handleAllRelatedTaxa(state, fromTaxon, classificationMap, fromRefFk);
360
									if (isDoubtful.getValue() == true){
361
										((TaxonRelationship)taxonRelationship).setDoubtful(true);
362
									}
363
								}
364
							} catch (UnknownCdmTypeException e) {
365
								logger.warn("TaxonRelationShipType " + relQualifierFk + " (conceptRelationship) not yet implemented");
366
								 success = false;
367
							}
368
						}else {
369
							logger.warn("TaxonRelationShipType " + relQualifierFk + " not yet implemented: RelPTaxonId = " + relPTaxonId );
370
							success = false;
371
						}
372

    
373
						if (taxonRelationship != null){
374
						    doNotes(taxonRelationship, notes);
375
						}else if (isNotBlank(notes)){
376
						    logger.warn("Notes for synonym relationship or unknown taxon relationship not handled. RelID: " + relPTaxonId + ". Note: " + notes);
377
						}
378
						taxaToSave.add(taxon2);
379

    
380
						//TODO
381
						//etc.
382
					}else{
383
						if (taxon2 != null && taxon1 == null){
384
							logger.warn("First taxon ("+taxon1Id+") for RelPTaxon " + relPTaxonId + " does not exist in store. RelType: " + relQualifierFk);
385
						}else if (taxon2 == null && taxon1 != null){
386
							logger.warn("Second taxon ("+taxon2Id +") for RelPTaxon " + relPTaxonId + " does not exist in store. RelType: " + relQualifierFk);
387
						}else{
388
							logger.warn("Both taxa ("+taxon1Id+","+taxon2Id +") for RelPTaxon " + relPTaxonId + " do not exist in store. RelType: " + relQualifierFk);
389
						}
390

    
391
						success = false;
392
					}
393
				} catch (Exception e) {
394
					logger.error("Exception occurred when trying to handle taxon relationship " + relPTaxonId + " relQualifierFK " + relQualifierFk + " (" + taxon1Id + ","+ taxon2Id + "): " + e.getMessage());
395
					e.printStackTrace();
396
				}
397
			}
398
		}catch(SQLException e){
399
			throw new RuntimeException(e);
400
		}
401
		logger.info("Taxa to save: " + taxaToSave.size());
402
		partitioner.startDoSave();
403
		getTaxonService().saveOrUpdate(taxaToSave);
404
		classificationMap = null;
405
		taxaToSave = null;
406

    
407
		return success;
408
	}
409

    
410

    
411
	private void handleAllRelatedTaxa(BerlinModelImportState state, Taxon taxon, Map<Integer, Classification> classificationMap, Integer secRefFk) {
412
		if (taxon.getTaxonNodes().size() > 0){
413
			return;
414
		}else{
415
			Classification classification = getClassificationTree(state, classificationMap, secRefFk);
416
			classification.addChildTaxon(taxon, null, null);
417
		}
418
	}
419

    
420
	@Override
421
	protected void doInvoke(BerlinModelImportState state){
422
		try {
423
			makeClassifications(state);
424
			super.doInvoke(state);
425
			makeFlatClassificationTaxa(state);
426
			return;
427
		} catch (SQLException e) {
428
			throw new RuntimeException(e);
429
		}
430

    
431
	}
432

    
433

    
434
	private void makeFlatClassificationTaxa(BerlinModelImportState state) {
435
		//Note: this part still does not use partitions
436
		logger.info("Flat classifications start");
437
		TransactionStatus txStatus = startTransaction();
438
		if (! state.getConfig().isIncludeFlatClassifications()){
439
			return;
440
		}
441
		String sql = " SELECT pt.PTRefFk AS secRefFk, pt.RIdentifier " +
442
						" FROM PTaxon AS pt " +
443
							" LEFT OUTER JOIN RelPTaxon ON pt.PTNameFk = RelPTaxon.PTNameFk2 AND pt.PTRefFk = RelPTaxon.PTRefFk2 " +
444
							"  LEFT OUTER JOIN RelPTaxon AS RelPTaxon_1 ON pt.PTNameFk = RelPTaxon_1.PTNameFk1 AND pt.PTRefFk = RelPTaxon_1.PTRefFk1 " +
445
						" WHERE (RelPTaxon_1.RelQualifierFk IS NULL) AND (dbo.RelPTaxon.RelQualifierFk IS NULL) " +
446
						" ORDER BY pt.PTRefFk "	;
447
		ResultSet rs = state.getConfig().getSource().getResultSet(sql);
448
		Map<Object, Map<String, ? extends CdmBase>> maps = getRelatedObjectsForFlatPartition(rs);
449

    
450
		Map<String, TaxonBase> taxonMap = (Map<String, TaxonBase>) maps.get(BerlinModelTaxonImport.NAMESPACE);
451
		Map<Integer, Classification> classificationMap = new HashMap<Integer, Classification>();
452

    
453
		rs = state.getConfig().getSource().getResultSet(sql);
454
		try {
455
			while (rs.next()){
456
				Integer treeRefFk = rs.getInt("secRefFk");
457
				String taxonId = rs.getString("RIdentifier");
458
				Classification classification = getClassificationTree(state, classificationMap, treeRefFk);
459
				TaxonBase<?> taxon = taxonMap.get(taxonId);
460
				if (taxon == null){
461
					String message = "TaxonBase for taxon id (%s) not found in taxonMap";
462
					logger.warn(String.format(message, taxonId, taxonId));
463
				}else if (taxon.isInstanceOf(Taxon.class)){
464
					classification.addChildTaxon(CdmBase.deproxy(taxon, Taxon.class), null, null);
465
				}else{
466
					String message = "TaxonBase for taxon is not of class Taxon but %s (RIdentifier %s)";
467
					logger.warn(String.format(message, taxon.getClass(), taxonId));
468
				}
469
			}
470
		} catch (SQLException e) {
471
			// TODO Auto-generated catch block
472
			e.printStackTrace();
473
		}
474
		commitTransaction(txStatus);
475
		logger.info("Flat classifications end");
476

    
477
	}
478

    
479
	@Override
480
	protected String getIdQuery(BerlinModelImportState state) {
481
		if (state.getConfig().getRelTaxaIdQuery() != null){
482
			return state.getConfig().getRelTaxaIdQuery();
483
		}else{
484
			return super.getIdQuery(state);
485
		}
486
	}
487

    
488
	@Override
489
	public Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForPartition( ResultSet rs, BerlinModelImportState state) {
490
		String nameSpace;
491
		Class<?> cdmClass;
492
		Set<String> idSet;
493
		Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<Object, Map<String, ? extends CdmBase>>();
494

    
495
		try{
496
			Set<String> taxonIdSet = new HashSet<String>();
497
			Set<String> referenceIdSet = new HashSet<String>();
498
//			Set<String> classificationIdSet = new HashSet<String>();
499
			while (rs.next()){
500
				handleForeignKey(rs, taxonIdSet, "taxon1Id");
501
				handleForeignKey(rs, taxonIdSet, "taxon2Id");
502
//				handleForeignKey(rs, classificationIdSet, "treeRefFk");
503
				handleForeignKey(rs, referenceIdSet, "RelRefFk");
504
	}
505

    
506
			//taxon map
507
			nameSpace = BerlinModelTaxonImport.NAMESPACE;
508
			cdmClass = TaxonBase.class;
509
			idSet = taxonIdSet;
510
			Map<String, TaxonBase> taxonMap = (Map<String, TaxonBase>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
511
			result.put(nameSpace, taxonMap);
512

    
513
//			//tree map
514
//			nameSpace = "Classification";
515
//			cdmClass = Classification.class;
516
//			idSet = classificationIdSet;
517
//			Map<String, Classification> treeMap = (Map<String, Classification>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
518
//			result.put(cdmClass, treeMap);
519
//			Set<UUID> treeUuidSet = state
520
//			getClassificationService().find(uuidSet);
521
//
522
			//reference map
523
			nameSpace = BerlinModelReferenceImport.REFERENCE_NAMESPACE;
524
			cdmClass = Reference.class;
525
			idSet = referenceIdSet;
526
			Map<String, Reference> referenceMap = (Map<String, Reference>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
527
			result.put(nameSpace, referenceMap);
528

    
529
		} catch (SQLException e) {
530
			throw new RuntimeException(e);
531
		}
532
		return result;
533
	}
534

    
535

    
536
	private Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForFlatPartition( ResultSet rs) {
537
		String nameSpace;
538
		Class cdmClass;
539
		Set<String> idSet;
540
		Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<Object, Map<String, ? extends CdmBase>>();
541

    
542
		try{
543
			Set<String> taxonIdSet = new HashSet<String>();
544
			Set<String> referenceIdSet = new HashSet<String>();
545
//			Set<String> classificationIdSet = new HashSet<String>();
546
			while (rs.next()){
547
				handleForeignKey(rs, taxonIdSet, "RIdentifier");
548
//				handleForeignKey(rs, classificationIdSet, "treeRefFk");
549
	}
550

    
551
			//taxon map
552
			nameSpace = BerlinModelTaxonImport.NAMESPACE;
553
			cdmClass = TaxonBase.class;
554
			idSet = taxonIdSet;
555
			Map<String, TaxonBase> taxonMap = (Map<String, TaxonBase>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
556
			result.put(nameSpace, taxonMap);
557

    
558
//			//tree map
559
//			nameSpace = "Classification";
560
//			cdmClass = Classification.class;
561
//			idSet = classificationIdSet;
562
//			Map<String, Classification> treeMap = (Map<String, Classification>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
563
//			result.put(cdmClass, treeMap);
564
//			Set<UUID> treeUuidSet = state
565
//			getClassificationService().find(uuidSet);
566
//
567

    
568
		} catch (SQLException e) {
569
			throw new RuntimeException(e);
570
		}
571
		return result;
572
	}
573

    
574

    
575
	private void makeSynRel (int relQualifierFk, Taxon toTaxon, Synonym synonym, Reference citation, String microcitation){
576
		if (citation != null && !citation.equals(synonym.getSec())){
577
		    logger.warn("A synonym relationship citation is given and differs from synonym secundum. This can not be handled in CDM");
578
		}
579
		if (isNotBlank(microcitation)  && !microcitation.equals(synonym.getSecMicroReference())){
580
            logger.warn("A synonym relationship microcitation is given and differs from synonym secundum micro reference. This can not be handled in CDM");
581
        }
582
	    if (relQualifierFk == TAX_REL_IS_HOMOTYPIC_SYNONYM_OF ||
583
				relQualifierFk == TAX_REL_IS_PROPARTE_HOMOTYPIC_SYNONYM_OF ||
584
				relQualifierFk == TAX_REL_IS_PARTIAL_HOMOTYPIC_SYNONYM_OF){
585
			toTaxon.addHomotypicSynonym(synonym);
586
		}else if (relQualifierFk == TAX_REL_IS_HETEROTYPIC_SYNONYM_OF ||
587
				relQualifierFk == TAX_REL_IS_PROPARTE_HETEROTYPIC_SYNONYM_OF ||
588
				relQualifierFk == TAX_REL_IS_PARTIAL_HETEROTYPIC_SYNONYM_OF){
589
			toTaxon.addSynonym(synonym, SynonymType.HETEROTYPIC_SYNONYM_OF());
590
		}else if (relQualifierFk == TAX_REL_IS_SYNONYM_OF ||
591
				relQualifierFk == TAX_REL_IS_PROPARTE_SYN_OF ||
592
				relQualifierFk == TAX_REL_IS_PARTIAL_SYN_OF){
593
			toTaxon.addSynonym(synonym, SynonymType.SYNONYM_OF());
594
		}else{
595
			logger.warn("SynonymyRelationShipType could not be defined for relQualifierFk " + relQualifierFk + ". 'Unknown'-Type taken instead.");
596
			toTaxon.addSynonym(synonym, SynonymType.SYNONYM_OF());
597
		}
598
		return;
599

    
600
	}
601

    
602
	private  boolean isSynonymRelationship(int relQualifierFk){
603
		if (relQualifierFk == TAX_REL_IS_SYNONYM_OF ||
604
			relQualifierFk == TAX_REL_IS_HOMOTYPIC_SYNONYM_OF ||
605
			relQualifierFk == TAX_REL_IS_HETEROTYPIC_SYNONYM_OF ||
606
			relQualifierFk == TAX_REL_IS_PROPARTE_SYN_OF ||
607
			relQualifierFk == TAX_REL_IS_PARTIAL_SYN_OF ||
608
			relQualifierFk == TAX_REL_IS_PROPARTE_HOMOTYPIC_SYNONYM_OF ||
609
			relQualifierFk == TAX_REL_IS_PROPARTE_HETEROTYPIC_SYNONYM_OF ||
610
			relQualifierFk == TAX_REL_IS_PARTIAL_HOMOTYPIC_SYNONYM_OF ||
611
			relQualifierFk == TAX_REL_IS_PARTIAL_HETEROTYPIC_SYNONYM_OF
612
		){
613
			return true;
614
		}else{
615
			return false;
616
		}
617
	}
618

    
619
	private  boolean isTaxonRelationship(int relQualifierFk){
620
		if (relQualifierFk == TAX_REL_IS_INCLUDED_IN ||
621
				relQualifierFk == TAX_REL_IS_MISAPPLIED_NAME_OF){
622
			return true;
623
		}else if (relQualifierFk == TAX_REL_IS_PROPARTE_SYN_OF ||
624
	                relQualifierFk == TAX_REL_IS_PARTIAL_SYN_OF ||
625
	                relQualifierFk == TAX_REL_IS_PROPARTE_HOMOTYPIC_SYNONYM_OF ||
626
	                relQualifierFk == TAX_REL_IS_PROPARTE_HETEROTYPIC_SYNONYM_OF ||
627
	                relQualifierFk == TAX_REL_IS_PARTIAL_HOMOTYPIC_SYNONYM_OF ||
628
	                relQualifierFk == TAX_REL_IS_PARTIAL_HETEROTYPIC_SYNONYM_OF
629
                    ){
630
	            return true;
631

    
632
		}else{
633
			return false;
634
		}
635
	}
636

    
637
	private TaxonNode makeTaxonomicallyIncluded(BerlinModelImportState state, Map<Integer, Classification> classificationMap, int treeRefFk, Taxon child, Taxon parent, Reference citation, String microCitation){
638
		Classification tree = getClassificationTree(state, classificationMap, treeRefFk);
639
		return tree.addParentChild(parent, child, citation, microCitation);
640
	}
641

    
642
	private Classification getClassificationTree(BerlinModelImportState state, Map<Integer, Classification> classificationMap, int treeRefFk) {
643
		if (state.getConfig().isUseSingleClassification()){
644
			if (state.getConfig().getSourceSecId() != null){
645
				treeRefFk = (Integer)state.getConfig().getSourceSecId();
646
			}else{
647
				treeRefFk = 1;
648
			}
649

    
650
		}
651
		Classification tree = classificationMap.get(treeRefFk);
652
		if (tree == null){
653
			UUID treeUuid = state.getTreeUuidByIntTreeKey(treeRefFk);
654
			if (treeUuid == null){
655
				throw new IllegalStateException("treeUUID does not exist in state for " + treeRefFk );
656
			}
657
			tree = getClassificationService().find(treeUuid);
658
			classificationMap.put(treeRefFk, tree);
659
		}
660
		if (tree == null){
661
			throw new IllegalStateException("Tree for ToTaxon reference " + treeRefFk + " does not exist.");
662
		}
663
		return tree;
664
	}
665

    
666
	@Override
667
	protected boolean doCheck(BerlinModelImportState state){
668
		IOValidator<BerlinModelImportState> validator = new BerlinModelTaxonRelationImportValidator();
669
		return validator.validate(state);
670
	}
671

    
672
	@Override
673
	protected boolean isIgnore(BerlinModelImportState state){
674
		return ! state.getConfig().isDoRelTaxa();
675
	}
676

    
677

    
678
}
(17-17/21)