Project

General

Profile

Download (15.4 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.T_STATUS_ACCEPTED;
13
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.T_STATUS_PARTIAL_SYN;
14
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.T_STATUS_PRO_PARTE_SYN;
15
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.T_STATUS_SYNONYM;
16
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.T_STATUS_UNRESOLVED;
17

    
18
import java.lang.reflect.Method;
19
import java.sql.ResultSet;
20
import java.sql.SQLException;
21
import java.util.HashMap;
22
import java.util.HashSet;
23
import java.util.Map;
24
import java.util.Set;
25
import java.util.UUID;
26

    
27
import org.apache.commons.lang.StringUtils;
28
import org.apache.log4j.Logger;
29
import org.springframework.stereotype.Component;
30

    
31
import eu.etaxonomy.cdm.database.update.DatabaseTypeNotSupportedException;
32
import eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer;
33
import eu.etaxonomy.cdm.io.berlinModel.in.validation.BerlinModelTaxonImportValidator;
34
import eu.etaxonomy.cdm.io.common.IOValidator;
35
import eu.etaxonomy.cdm.io.common.ResultSetPartitioner;
36
import eu.etaxonomy.cdm.model.agent.Person;
37
import eu.etaxonomy.cdm.model.common.CdmBase;
38
import eu.etaxonomy.cdm.model.common.Extension;
39
import eu.etaxonomy.cdm.model.common.ExtensionType;
40
import eu.etaxonomy.cdm.model.common.Language;
41
import eu.etaxonomy.cdm.model.common.Marker;
42
import eu.etaxonomy.cdm.model.common.MarkerType;
43
import eu.etaxonomy.cdm.model.description.Feature;
44
import eu.etaxonomy.cdm.model.description.TaxonDescription;
45
import eu.etaxonomy.cdm.model.description.TextData;
46
import eu.etaxonomy.cdm.model.name.TaxonName;
47
import eu.etaxonomy.cdm.model.reference.Reference;
48
import eu.etaxonomy.cdm.model.taxon.Synonym;
49
import eu.etaxonomy.cdm.model.taxon.Taxon;
50
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
51

    
52

    
53
/**
54
 * @author a.mueller
55
 * @since 20.03.2008
56
 */
57
@Component
58
public class BerlinModelTaxonImport  extends BerlinModelImportBase {
59
    /**
60
     *
61
     */
62
    private static final String LAST_SCRUTINY_FK = "lastScrutinyFk";
63

    
64
    private static final long serialVersionUID = -1186364983750790695L;
65

    
66
    private static final Logger logger = Logger.getLogger(BerlinModelTaxonImport.class);
67

    
68
	public static final String NAMESPACE = "Taxon";
69

    
70
	private static final String pluralString = "Taxa";
71
	private static final String dbTableName = "PTaxon";
72

    
73
	/**
74
	 * How should the publish flag in table PTaxon be interpreted
75
	 * NO_MARKER: No marker is set
76
	 * ONLY_FALSE:
77
	 */
78
	public enum PublishMarkerChooser{
79
		NO_MARKER,
80
		ONLY_FALSE,
81
		ONLY_TRUE,
82
		ALL;
83

    
84
		boolean doMark(boolean value){
85
			if (value == true){
86
				return this == ALL || this == ONLY_TRUE;
87
			}else{
88
				return this == ALL || this == ONLY_FALSE;
89
			}
90
		}
91
	}
92

    
93
	public BerlinModelTaxonImport(){
94
		super(dbTableName, pluralString);
95
	}
96

    
97
	@Override
98
	protected String getIdQuery(BerlinModelImportState state) {
99
		String sqlSelect = " SELECT RIdentifier";
100
		String taxonTable = state.getConfig().getTaxonTable();
101
		String sqlFrom = String.format(" FROM %s ", taxonTable);
102
		String sqlWhere = "";
103

    
104
		String sql = sqlSelect + " " + sqlFrom + " " + sqlWhere ;
105
		return sql;
106
	}
107

    
108
	@Override
109
	protected String getRecordQuery(BerlinModelImportConfigurator config) {
110
		String sqlSelect = " SELECT pt.*  ";
111
		String sqlFrom = " FROM PTaxon pt ";
112
		if (config.isEuroMed()){
113
			sqlFrom = " FROM PTaxon AS pt " +
114
							" INNER JOIN v_cdm_exp_taxaAll AS em ON pt.RIdentifier = em.RIdentifier ";
115
			if (!config.isUseLastScrutinyAsSec()){
116
			    sqlFrom += " LEFT OUTER JOIN Reference r ON pt.LastScrutinyFk = r.RefId ";
117
			}
118
			sqlSelect += " , em.MA ";
119
			if (!config.isUseLastScrutinyAsSec()){
120
			    sqlSelect += ", r.RefCache as LastScrutiny ";
121
            }
122
		}
123

    
124

    
125
		String sqlWhere = " WHERE ( pt.RIdentifier IN (" + ID_LIST_TOKEN + ") )";
126

    
127
		String strRecordQuery =sqlSelect + " " + sqlFrom + " " + sqlWhere ;
128
//			" SELECT * " +
129
//			" FROM PTaxon " + state.getConfig().getTaxonTable();
130
//			" WHERE ( RIdentifier IN (" + ID_LIST_TOKEN + ") )";
131
		return strRecordQuery;
132
	}
133

    
134
	@Override
135
	protected boolean doCheck(BerlinModelImportState state){
136
		IOValidator<BerlinModelImportState> validator = new BerlinModelTaxonImportValidator();
137
		return validator.validate(state);
138
	}
139

    
140
	@Override
141
	public boolean doPartition(ResultSetPartitioner partitioner, BerlinModelImportState state) {
142
		boolean success = true ;
143

    
144
		BerlinModelImportConfigurator config = state.getConfig();
145
		Set<TaxonBase> taxaToSave = new HashSet<>();
146
		Map<String, TaxonName> taxonNameMap = partitioner.getObjectMap(BerlinModelTaxonNameImport.NAMESPACE);
147
		Map<String, Reference> refMap = partitioner.getObjectMap(BerlinModelReferenceImport.REFERENCE_NAMESPACE);
148

    
149
		ResultSet rs = partitioner.getResultSet();
150
		try{
151
			boolean publishFlagExists = state.getConfig().getSource().checkColumnExists("PTaxon", "PublishFlag");
152
			boolean isEuroMed = config.isEuroMed();
153
			while (rs.next()){
154

    
155
			//	if ((i++ % modCount) == 0 && i!= 1 ){ logger.info("PTaxa handled: " + (i-1));}
156

    
157
				//create TaxonName element
158
				int taxonId = rs.getInt("RIdentifier");
159
				int statusFk = rs.getInt("statusFk");
160

    
161
				int nameFk = rs.getInt("PTNameFk");
162
				int refFkInt = rs.getInt("PTRefFk");
163
				String doubtful = rs.getString("DoubtfulFlag");
164
				String uuid = null;
165
				if (resultSetHasColumn(rs,"UUID")){
166
					uuid = rs.getString("UUID");
167
				}
168

    
169

    
170
				TaxonName taxonName = null;
171
				taxonName  = taxonNameMap.get(String.valueOf(nameFk));
172

    
173
				Reference reference = null;
174
				String refFkStr = String.valueOf(refFkInt);
175
				reference = refMap.get(refFkStr);
176

    
177
				Reference lastScrutinyRef = null;
178
                if (state.getConfig().isUseLastScrutinyAsSec() && resultSetHasColumn(rs,LAST_SCRUTINY_FK)){
179
                    Integer lastScrutinyFk = nullSafeInt(rs,LAST_SCRUTINY_FK);
180
                    if (lastScrutinyFk != null){
181
                        String lastScrutinyFkStr = String.valueOf(lastScrutinyFk);
182
                        if (lastScrutinyFkStr != null){
183
                            lastScrutinyRef = refMap.get(lastScrutinyFkStr);
184
                            if (lastScrutinyRef == null){
185
                                logger.warn("Last scrutiny reference "+lastScrutinyFkStr+" could not be found "
186
                                        + "for taxon " + taxonId);
187
                            }
188
                            //MANs do have last scrutiny => the following is not correct
189
//                            if(!StringUtils.right(refFkStr, 5).equals("00000")){
190
//                                logger.warn("Unexpected secFk " + refFkStr + " for taxon with last scrutiny. Taxon id " + taxonId);
191
//                            }
192
                        }
193
                    }
194
                }
195

    
196
				if(! config.isIgnoreNull()){
197
					if (taxonName == null ){
198
						logger.warn("TaxonName belonging to taxon (RIdentifier = " + taxonId + ") could not be found in store. Taxon will not be imported");
199
						success = false;
200
						continue; //next taxon
201
					}else if (reference == null ){
202
						logger.warn("Sec Reference belonging to taxon could not be found in store. Taxon will not be imported");
203
						success = false;
204
						continue; //next taxon
205
					}
206
				}
207
				TaxonBase<?> taxonBase;
208
				Synonym synonym;
209
				Taxon taxon;
210
				Reference sec = lastScrutinyRef != null? lastScrutinyRef: reference;
211
				try {
212
					logger.debug(statusFk);
213
					if (statusFk == T_STATUS_ACCEPTED || statusFk == T_STATUS_UNRESOLVED
214
					        || statusFk == T_STATUS_PRO_PARTE_SYN || statusFk == T_STATUS_PARTIAL_SYN ){
215
						taxon = Taxon.NewInstance(taxonName, sec);
216
						taxonBase = taxon;
217
						if (statusFk == T_STATUS_UNRESOLVED){
218
							taxon.setTaxonStatusUnknown(true);
219
						}
220
						//TODO marker for pp and partial?
221
					}else if (statusFk == T_STATUS_SYNONYM ){
222
						synonym = Synonym.NewInstance(taxonName, sec);
223
						taxonBase = synonym;
224
//						if (statusFk == T_STATUS_PRO_PARTE_SYN){
225
//						    synonym.setProParte(true);
226
//						}
227
//						if (statusFk == T_STATUS_PARTIAL_SYN){
228
//							synonym.setPartial(true);
229
//						}
230
					}else{
231
						logger.warn("TaxonStatus " + statusFk + " not yet implemented. Taxon (RIdentifier = " + taxonId + ") left out.");
232
						success = false;
233
						continue;
234
					}
235
					if (uuid != null){
236
						taxonBase.setUuid(UUID.fromString(uuid));
237
					}
238

    
239
					//doubtful
240
					if (doubtful.equals("a")){
241
						taxonBase.setDoubtful(false);
242
					}else if(doubtful.equals("d")){
243
						taxonBase.setDoubtful(true);
244
					}else if(doubtful.equals("i")){
245
						taxonBase.setDoubtful(false);
246
						logger.warn("Doubtful = i (inactivated) does not exist in CDM. Doubtful set to false. RIdentifier: " + taxonId);
247
					}
248

    
249
					//detail
250
					String detail = rs.getString("Detail");
251
					if (isNotBlank(detail)){
252
						ExtensionType detailExtensionType = getExtensionType(state, BerlinModelTransformer.DETAIL_EXT_UUID, "micro reference","micro reference","micro ref.");
253
						Extension.NewInstance(taxonBase, detail, detailExtensionType);
254
					}
255
					//idInSource
256
					String idInSource = rs.getString("IdInSource");
257
					if (isNotBlank(idInSource)){
258
						ExtensionType detailExtensionType = getExtensionType(state, BerlinModelTransformer.ID_IN_SOURCE_EXT_UUID, "Berlin Model IdInSource","Berlin Model IdInSource","BM source id");
259
						Extension.NewInstance(taxonBase, idInSource, detailExtensionType);
260
					}
261
					//namePhrase
262
					String namePhrase = rs.getString("NamePhrase");
263
					if (StringUtils.isNotBlank(namePhrase)){
264
						taxonBase.setAppendedPhrase(namePhrase);
265
					}
266
					//useNameCache
267
					Boolean useNameCacheFlag = rs.getBoolean("UseNameCacheFlag");
268
					if (useNameCacheFlag){
269
						taxonBase.setUseNameCache(true);
270
					}
271
					//publisheFlag
272
					if (publishFlagExists){
273
						Boolean publishFlag = rs.getBoolean("PublishFlag");
274
						Boolean misapplied = false;
275
						if (isEuroMed){
276
							misapplied = rs.getBoolean("MA");
277
						}
278

    
279
						if ( ! misapplied){
280
							taxonBase.setPublish(publishFlag);
281
						}
282
					}
283

    
284
					//  does not exist anymore as we use last scrutiny now as sec ref
285
					if (!state.getConfig().isUseLastScrutinyAsSec() && resultSetHasColumn(rs, "LastScrutiny")){
286
						String lastScrutiny = rs.getString("LastScrutiny");
287
						//TODO strange, why not Extension last scrutiny? To match PESI? Is there a difference
288
						//to LastScrutinyFK and SpeciesExpertFK?
289
						if (isNotBlank(lastScrutiny)){
290
						    ExtensionType extensionTypeSpeciesExpert = getExtensionType(state, BerlinModelTransformer.uuidSpeciesExpertName, "Species Expert", "Species Expert", "Species Expert");
291
						    taxonBase.addExtension(lastScrutiny, extensionTypeSpeciesExpert);
292
						    ExtensionType extensionTypeExpert = getExtensionType(state, BerlinModelTransformer.uuidExpertName, "Expert", "Expert for a taxonomic group", "Expert");
293
						    taxonBase.addExtension(lastScrutiny, extensionTypeExpert);
294
						}
295
					}
296
					//
297
					if (resultSetHasColumn(rs, "IsExcludedMarker")){
298
					    boolean isExcluded = rs.getBoolean("IsExcludedMarker");
299
					    if (isExcluded){
300
					        String extension = rs.getString("IsExcludedExtension");
301
					        String valueless = "not accepted: taxonomically valueless local or singular biotype";
302
					        String provisional = "provisional: probably a taxonomically valueless local or singular biotype";
303

    
304
					        MarkerType markerType = null;
305
					        if (valueless.equals(extension)){
306
					            markerType = getMarkerType(state, BerlinModelTransformer.uuidTaxonomicallyValueless, "taxonomically valueless", valueless, "valueless", getEuroMedMarkerTypeVoc());
307
					        }else if (provisional.equals(extension)){
308
                                markerType = getMarkerType(state, BerlinModelTransformer.uuidProbablyTaxonomicallyValueless, "probably taxonomically valueless", provisional, "provisional", getEuroMedMarkerTypeVoc());
309
                            }
310
					        if (markerType != null){
311
					            taxonBase.addMarker(Marker.NewInstance(markerType, true));
312
					        }else{
313
					            logger.warn("IsExcludedExtension not regonized for taxon " + taxonId + "; " + extension);
314
					        }
315
					    }
316
					}
317

    
318
					//Notes
319
					boolean excludeNotes = state.getConfig().isTaxonNoteAsFeature() && taxonBase.isInstanceOf(Taxon.class);
320
					doIdCreatedUpdatedNotes(state, taxonBase, rs, taxonId, NAMESPACE, false, excludeNotes);
321
					if (excludeNotes){
322
					    makeTaxonomicNote(state, CdmBase.deproxy(taxonBase, Taxon.class), rs.getString("Notes"));
323
					}
324

    
325
					//external url
326
					if (config.getMakeUrlForTaxon() != null){
327
						Method urlMethod = config.getMakeUrlForTaxon();
328
						urlMethod.invoke(null, taxonBase, rs);
329
					}
330

    
331
					partitioner.startDoSave();
332
					taxaToSave.add(taxonBase);
333
				} catch (Exception e) {
334
					logger.warn("An exception (" +e.getMessage()+") occurred when creating taxon with id " + taxonId + ". Taxon could not be saved.");
335
					success = false;
336
				}
337
			}
338
		} catch (DatabaseTypeNotSupportedException e) {
339
			logger.error("MethodNotSupportedException:" +  e);
340
			return false;
341
		} catch (Exception e) {
342
			logger.error("SQLException:" +  e);
343
			return false;
344
		}
345

    
346
		getTaxonService().save(taxaToSave);
347
		return success;
348
	}
349

    
350
	/**
351
     * @param state
352
     * @param taxonBase
353
	 * @param notes
354
     */
355
    private void makeTaxonomicNote(BerlinModelImportState state, Taxon taxon, String notes) {
356
        if (isNotBlank(notes)){
357
            TaxonDescription desc = getTaxonDescription(taxon, false, true);
358
            desc.setDefault(true);  //hard coded for Salvador, not used elsewhere as far as I can see
359
            TextData textData = TextData.NewInstance(Feature.NOTES() , notes, Language.SPANISH_CASTILIAN(), null);
360
            desc.addElement(textData);
361
        }
362
    }
363

    
364
    @Override
365
	public Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForPartition(ResultSet rs, BerlinModelImportState state) {
366
		String nameSpace;
367
		Class<?> cdmClass;
368
		Set<String> idSet;
369
		Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<>();
370

    
371
		try{
372
			Set<String> nameIdSet = new HashSet<>();
373
			Set<String> referenceIdSet = new HashSet<>();
374
			while (rs.next()){
375
				handleForeignKey(rs, nameIdSet, "PTNameFk");
376
				handleForeignKey(rs, referenceIdSet, "PTRefFk");
377
				if (state.getConfig().isUseLastScrutinyAsSec() && resultSetHasColumn(rs, LAST_SCRUTINY_FK)){
378
				    handleForeignKey(rs, referenceIdSet, LAST_SCRUTINY_FK);
379
				}
380
			}
381

    
382
			//name map
383
			nameSpace = BerlinModelTaxonNameImport.NAMESPACE;
384
			cdmClass = TaxonName.class;
385
			idSet = nameIdSet;
386
			Map<String, Person> nameMap = (Map<String, Person>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
387
			result.put(nameSpace, nameMap);
388

    
389
			//reference map
390
			nameSpace = BerlinModelReferenceImport.REFERENCE_NAMESPACE;
391
			cdmClass = Reference.class;
392
			idSet = referenceIdSet;
393
			Map<String, Reference> referenceMap = (Map<String, Reference>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
394
			result.put(nameSpace, referenceMap);
395

    
396
		} catch (SQLException e) {
397
			throw new RuntimeException(e);
398
		}
399
		return result;
400
	}
401

    
402
	@Override
403
	protected String getTableName() {
404
		return dbTableName;
405
	}
406

    
407
	@Override
408
	public String getPluralString() {
409
		return pluralString;
410
	}
411

    
412
	@Override
413
	protected boolean isIgnore(BerlinModelImportState state){
414
		return ! state.getConfig().isDoTaxa();
415
	}
416

    
417
}
(14-14/21)