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
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<TaxonBase>();
240
		Map<String, TaxonBase> taxonMap = partitioner.getObjectMap(BerlinModelTaxonImport.NAMESPACE);
241
		Map<Integer, Classification> classificationMap = new HashMap<Integer, Classification>();
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
								//pro parte already set by taxon mapping
326
//							}else if (relQualifierFk == TAX_REL_IS_PROPARTE_SYN_OF ||
327
//									relQualifierFk == TAX_REL_IS_PROPARTE_HOMOTYPIC_SYNONYM_OF ||
328
//									relQualifierFk == TAX_REL_IS_PROPARTE_HETEROTYPIC_SYNONYM_OF ){
329
//									synonym.setProParte(true);
330
//							}else if(relQualifierFk == TAX_REL_IS_PARTIAL_SYN_OF ||
331
//									relQualifierFk == TAX_REL_IS_PARTIAL_HOMOTYPIC_SYNONYM_OF ||
332
//									relQualifierFk == TAX_REL_IS_PARTIAL_HETEROTYPIC_SYNONYM_OF ){
333
//							        synonym.setPartial(true);
334
							}else{
335
								success = false;
336
								logger.warn("Synonym relationship type not yet implemented: " + relQualifierFk);
337
							}
338
						}else if (isConceptRelationship){
339
							ResultWrapper<Boolean> isInverse = ResultWrapper.NewInstance(false);
340
							ResultWrapper<Boolean> isDoubtful = ResultWrapper.NewInstance(false);
341
							try {
342
								TaxonRelationshipType relType = BerlinModelTransformer.taxonRelId2TaxonRelType(relQualifierFk, isInverse, isDoubtful);
343

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

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

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

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

    
404
		return success;
405
	}
406

    
407

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

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

    
428
	}
429

    
430

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

    
447
		Map<String, TaxonBase> taxonMap = (Map<String, TaxonBase>) maps.get(BerlinModelTaxonImport.NAMESPACE);
448
		Map<Integer, Classification> classificationMap = new HashMap<Integer, Classification>();
449

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

    
474
	}
475

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

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

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

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

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

    
526
		} catch (SQLException e) {
527
			throw new RuntimeException(e);
528
		}
529
		return result;
530
	}
531

    
532

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

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

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

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

    
565
		} catch (SQLException e) {
566
			throw new RuntimeException(e);
567
		}
568
		return result;
569
	}
570

    
571

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

    
597
	}
598

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

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

    
629
		}else{
630
			return false;
631
		}
632
	}
633

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

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

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

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

    
669
	@Override
670
	protected boolean isIgnore(BerlinModelImportState state){
671
		return ! state.getConfig().isDoRelTaxa();
672
	}
673

    
674

    
675
}
(17-17/21)