Project

General

Profile

Download (29.3 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 java.sql.ResultSet;
13
import java.sql.SQLException;
14
import java.util.ArrayList;
15
import java.util.HashMap;
16
import java.util.HashSet;
17
import java.util.List;
18
import java.util.Map;
19
import java.util.Set;
20
import java.util.SortedSet;
21
import java.util.TreeSet;
22
import java.util.UUID;
23

    
24
import org.apache.commons.lang.StringUtils;
25
import org.apache.log4j.Logger;
26
import org.springframework.stereotype.Component;
27

    
28
import eu.etaxonomy.cdm.common.CdmUtils;
29
import eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer;
30
import eu.etaxonomy.cdm.io.berlinModel.in.validation.BerlinModelCommonNamesImportValidator;
31
import eu.etaxonomy.cdm.io.common.IOValidator;
32
import eu.etaxonomy.cdm.io.common.ResultSetPartitioner;
33
import eu.etaxonomy.cdm.io.common.Source;
34
import eu.etaxonomy.cdm.io.common.TdwgAreaProvider;
35
import eu.etaxonomy.cdm.model.common.Annotation;
36
import eu.etaxonomy.cdm.model.common.AnnotationType;
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.common.Representation;
44
import eu.etaxonomy.cdm.model.description.CommonTaxonName;
45
import eu.etaxonomy.cdm.model.description.DescriptionElementSource;
46
import eu.etaxonomy.cdm.model.description.TaxonDescription;
47
import eu.etaxonomy.cdm.model.location.Country;
48
import eu.etaxonomy.cdm.model.location.NamedArea;
49
import eu.etaxonomy.cdm.model.name.TaxonName;
50
import eu.etaxonomy.cdm.model.reference.Reference;
51
import eu.etaxonomy.cdm.model.taxon.Taxon;
52
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
53

    
54
/**
55
 *
56
 * @author a.mueller
57
 * @since 20.03.2008
58
 */
59
@Component
60
public class BerlinModelCommonNamesImport  extends BerlinModelImportBase {
61
    private static final long serialVersionUID = -8921948187177864321L;
62

    
63
    private static final Logger logger = Logger.getLogger(BerlinModelCommonNamesImport.class);
64

    
65
	public static final UUID REFERENCE_LANGUAGE_ISO639_2_UUID = UUID.fromString("40c4f8dd-3d9c-44a4-b77a-76e137a89a5f");
66
	public static final UUID REFERENCE_LANGUAGE_STRING_UUID = UUID.fromString("2a1b678f-c27d-48c1-b43e-98fd0d426305");
67
	public static final UUID STATUS_ANNOTATION_UUID = UUID.fromString("e3f7b80a-1286-458d-812c-5e818f731968");
68

    
69
	public static final String NAMESPACE = "common name";
70

    
71

    
72
	private static final String pluralString = "common names";
73
	private static final String dbTableName = "emCommonName";
74

    
75

    
76
	//map that stores the regions (named areas) and makes them accessible via the regionFk
77
	private Map<String, NamedArea> regionMap = new HashMap<>();
78

    
79
	public BerlinModelCommonNamesImport(){
80
		super(dbTableName, pluralString);
81
	}
82

    
83
	@Override
84
	protected String getIdQuery(BerlinModelImportState state) {
85
		String result = " SELECT CommonNameId FROM emCommonName WHERE (1=1) ";
86
		if (isNotBlank(state.getConfig().getCommonNameFilter())){
87
			result += " AND " + state.getConfig().getCommonNameFilter();
88
		}
89
		result += " ORDER BY CommonNameId ";
90

    
91
		return result;
92
	}
93

    
94
	@Override
95
	protected String getRecordQuery(BerlinModelImportConfigurator config) {
96
		String recordQuery = "";
97
		recordQuery =
98
				" SELECT rel.RelPTaxonId, rel.RelQualifierFk, acc.RIdentifier accTaxonId, factTaxon.RIdentifier factTaxonId, accName.NameId, f.FactId, " +
99
				           "       cn.CommonNameId, cn.CommonName, tax.RIdentifier AS taxonId, cn.PTNameFk, cn.RefFk AS refId, cn.Status, cn.RegionFks, cn.MisNameRefFk, " +
100
					       "       cn.NameInSourceFk, cn.Created_When, cn.Updated_When, cn.Created_Who, cn.Updated_Who, cn.Note AS Notes, languageCommonName.Language, " +
101
					       "       languageCommonName.LanguageOriginal, languageCommonName.ISO639_1, languageCommonName.ISO639_2,   " +
102
					       "       emLanguageReference.RefFk AS languageRefRefFk, emLanguageReference.ReferenceShort, emLanguageReference.ReferenceLong,  " +
103
					       "       emLanguageReference.LanguageFk, languageReferenceLanguage.Language AS refLanguage, languageReferenceLanguage.ISO639_2 AS refLanguageIso639_2,  "+
104
					       "       misappliedTaxon.RIdentifier AS misappliedTaxonId " +
105
				  " FROM  PTaxon AS misappliedTaxon RIGHT OUTER JOIN " +
106
					       "      emLanguage AS languageReferenceLanguage RIGHT OUTER JOIN " +
107
			               "      emLanguageReference ON languageReferenceLanguage.LanguageId = emLanguageReference.LanguageFk RIGHT OUTER JOIN " +
108
			               "      emCommonName AS cn INNER JOIN " +
109
			               "      PTaxon AS tax ON cn.PTNameFk = tax.PTNameFk AND cn.PTRefFk = tax.PTRefFk ON  " +
110
			               "      emLanguageReference.ReferenceId = cn.LanguageRefFk LEFT OUTER JOIN " +
111
			               "      emLanguage AS languageCommonName ON cn.LanguageFk = languageCommonName.LanguageId ON misappliedTaxon.PTNameFk = cn.NameInSourceFk AND  " +
112
			               "      misappliedTaxon.PTRefFk = cn.MisNameRefFk " +
113

    
114
	                     "     LEFT OUTER JOIN Fact f ON cn.CommonNameId = f.ExtensionFk " +
115
	                     "     LEFT OUTER JOIN PTaxon factTaxon ON factTaxon.PTNameFk = f.PTNameFk AND factTaxon.PTRefFk = f.PTRefFk " +
116
	                     "     LEFT OUTER JOIN RelPTaxon rel ON rel.PTNameFk1 = tax.PTNameFk AND rel.PTRefFk1 = tax.PTRefFk AND rel.RelQualifierFk IN (2,6,7) " +
117
                         "     LEFT OUTER JOIN PTaxon acc ON rel.PTNameFk2 = acc.PTNameFk AND rel.PTRefFk2 = acc.PTRefFk " +
118
                         "     LEFT OUTER JOIN Name accName ON accName.NameId = acc.PTNameFk " +
119
			        " WHERE cn.CommonNameId IN (" + ID_LIST_TOKEN + ") " +
120
			        " ORDER BY cn.CommonNameId ";
121

    
122
		return recordQuery;
123
	}
124

    
125
	@Override
126
	protected void doInvoke(BerlinModelImportState state) {
127
		try {
128
			makeRegions(state);
129
		} catch (Exception e) {
130
			logger.error("Error when creating common name regions:" + e.getMessage());
131
			e.printStackTrace();
132
			state.setUnsuccessfull();
133
		}
134
		super.doInvoke(state);
135
		return;
136
	}
137

    
138
	/**
139
	 * @param state
140
	 *
141
	 */
142
	private void makeRegions(BerlinModelImportState state) {
143
		try {
144
			SortedSet<Integer> regionFks = new TreeSet<>();
145
			Source source = state.getConfig().getSource();
146

    
147
			//fill set with all regionFk from emCommonName.regionFks
148
			getRegionFks(state, regionFks, source);
149
			//concat filter string
150
			String sqlWhere = getSqlWhere(regionFks);
151

    
152
			//get E+M - TDWG Mapping
153
			Map<String, String> emTdwgMap = getEmTdwgMap(source);
154
			//fill regionMap
155
			fillRegionMap(state, sqlWhere, emTdwgMap);
156

    
157
			return;
158
		} catch (NumberFormatException e) {
159
			e.printStackTrace();
160
			state.setUnsuccessfull();
161
			return;
162
		} catch (SQLException e) {
163
			e.printStackTrace();
164
			state.setUnsuccessfull();
165
			return;
166
		}
167
	}
168

    
169

    
170
	@Override
171
	public boolean doPartition(ResultSetPartitioner partitioner, BerlinModelImportState state)  {
172
		boolean success = true ;
173

    
174
		Set<TaxonBase> taxaToSave = new HashSet<>();
175
		@SuppressWarnings("unchecked")
176
        Map<String, Taxon> taxonMap = partitioner.getObjectMap(BerlinModelTaxonImport.NAMESPACE);
177
		@SuppressWarnings("unchecked")
178
        Map<String, TaxonName> taxonNameMap = partitioner.getObjectMap(BerlinModelTaxonNameImport.NAMESPACE);
179
		@SuppressWarnings("unchecked")
180
        Map<String, Reference> refMap = partitioner.getObjectMap(BerlinModelReferenceImport.REFERENCE_NAMESPACE);
181

    
182
		Map<String, Language> iso6392Map = new HashMap<>();
183

    
184
	//	logger.warn("MisappliedNameRefFk  not yet implemented for Common Names");
185

    
186
		ResultSet rs = partitioner.getResultSet();
187
		Integer lastCommonNameId = null;
188
		try{
189
			while (rs.next()){
190

    
191
				//create TaxonName element
192
				Integer commonNameId = rs.getInt("CommonNameId");
193
				int taxonId = rs.getInt("taxonId");
194
				Integer factTaxonId = nullSafeInt(rs, "factTaxonId");
195
				Integer accTaxonId = nullSafeInt(rs, "accTaxonId");  //if common name is related to synonym this is the accepted taxon id
196

    
197
				Integer refId = nullSafeInt(rs, "refId");
198
//				Integer ptNameFk = nullSafeInt(rs,"PTNameFk");
199
				String commonNameString = rs.getString("CommonName");
200
				String iso639_2 = rs.getString("ISO639_2");
201
				String iso639_1 = rs.getString("ISO639_1");
202
				String languageString = rs.getString("Language");
203
				String originalLanguageString = rs.getString("LanguageOriginal");
204
				Integer misNameRefFk = nullSafeInt(rs, "MisNameRefFk");
205
				Integer languageRefRefFk = nullSafeInt(rs, "languageRefRefFk");
206
				String refLanguage = rs.getString("refLanguage");
207
				String refLanguageIso639_2 = rs.getString("refLanguageIso639_2");
208
				String status = rs.getString("Status");
209
				Integer nameInSourceFk = nullSafeInt( rs, "NameInSourceFk");
210
				Integer misappliedTaxonId = nullSafeInt( rs, "misappliedTaxonId");
211

    
212
				if (commonNameId == lastCommonNameId){
213
				    logger.warn("CommonNameId >1 times in query. This may happen due to LEFT JOINS to fact and/or accepted taxon and e.g. multiple taxon relationships. 2018-04-01 no such double relation existed in E+M. ");
214
				}else{
215
				    lastCommonNameId = commonNameId;
216
				}
217

    
218
				//regions
219
				String regionFks  = rs.getString("RegionFks");
220
				String[] regionFkSplit = (regionFks==null)? new String[0] : regionFks.split(",");
221

    
222
				//commonNameString
223
				if (isBlank(commonNameString)){
224
					String message = "CommonName is empty or null. Do not import record for taxon " + taxonId;
225
					logger.warn(message);
226
					continue;
227
				}
228

    
229
				//taxon
230
				Taxon taxon = null;
231
				TaxonBase<?> taxonBase  = taxonMap.get(String.valueOf(taxonId));
232
				if (taxonBase == null){
233
					logger.warn("Taxon (" + taxonId + ") could not be found. Common name " + commonNameString + "(" + commonNameId + ") not imported");
234
					continue;
235
				}else if (taxonBase.isInstanceOf(Taxon.class)){
236
				    taxon = CdmBase.deproxy(taxonBase, Taxon.class);
237
				    if (factTaxonId != null && !factTaxonId.equals(taxonId)){
238
				        logger.warn("Fact taxon ("+factTaxonId+") for common name "+commonNameId+" differs from common name taxon " + taxonId);
239
				    }
240
				}else{
241
				    Taxon factTaxon = null;
242
				    if (factTaxonId != null && factTaxonId.equals(accTaxonId)){
243
				        factTaxon = taxonMap.get(String.valueOf(factTaxonId));
244
				    }
245
				    if (factTaxon != null){
246
				        taxon = factTaxon;
247
				    }else{
248
				        logger.warn("taxon (" + taxonId + ") is not accepted. Can't import common name " +  commonNameId + ". FactTaxonId= " +  factTaxonId + "; accTaxonId = " + accTaxonId);
249
				        continue;
250
				    }
251
				}
252

    
253
				//Language
254
				Language language = getAndHandleLanguage(iso6392Map, iso639_2, iso639_1, languageString, originalLanguageString, state);
255

    
256
				//CommonTaxonName
257
				List<CommonTaxonName> commonTaxonNames = new ArrayList<>();
258
				for (String regionFk : regionFkSplit){ //
259
					CommonTaxonName commonTaxonName;
260
					if (commonTaxonNames.size() == 0){
261
						commonTaxonName = CommonTaxonName.NewInstance(commonNameString, language);
262
					}else{
263
						commonTaxonName = (CommonTaxonName)commonTaxonNames.get(0).clone();
264
					}
265
					commonTaxonNames.add(commonTaxonName);
266
					regionFk = regionFk.trim();
267
					NamedArea area = regionMap.get(regionFk);
268
					if (area == null){
269
						if (regionFkSplit.length > 1 && isNotBlank(regionFk)){
270
							logger.warn("Area for " + regionFk + " not defined in regionMap.");
271
						}else{
272
							//no region is defined
273
						}
274
					}else{
275
						commonTaxonName.setArea(area);
276
						TaxonDescription description = getDescription(taxon);
277
						description.addElement(commonTaxonName);
278
					}
279
				}
280

    
281
				//Reference/Source
282
				if (! CdmUtils.nullSafeEqual(refId, languageRefRefFk)){
283
					//use strRefId if languageRefFk is null
284
					if (languageRefRefFk == null){
285
						languageRefRefFk = refId;
286
					}else{
287
						logger.warn("CommonName.RefFk (" + CdmUtils.Nz(refId) + ") and LanguageReference.RefFk " + languageRefRefFk  + " are not equal. I will import only languageReference.RefFk");
288
					}
289
				}
290

    
291
				Reference reference = refMap.get(String.valueOf(languageRefRefFk));
292
				if (reference == null && languageRefRefFk != null){
293
					logger.warn("CommonName reference was null but reference exists. languageRefRefFk = " + languageRefRefFk + "; commonNameId = " + commonNameId);
294
				}
295
				String microCitation = null;
296
				String originalNameString = null;
297

    
298
				TaxonName nameUsedInSource = taxonNameMap.get(String.valueOf(nameInSourceFk));
299
				if (nameInSourceFk != null && nameUsedInSource == null){
300
					logger.warn("Name used in source (" + nameInSourceFk + ") was not found for common name " + commonNameId);
301
				}
302
				for (CommonTaxonName commonTaxonName : commonTaxonNames){
303
				    DescriptionElementSource source = DescriptionElementSource.NewPrimarySourceInstance(reference, microCitation, nameUsedInSource, originalNameString);
304
	                commonTaxonName.addSource(source);
305
				}
306

    
307

    
308
				//MisNameRef
309
				if (misNameRefFk != null){
310
					//Taxon misappliedName = getMisappliedName(biblioRefMap, nomRefMap, misNameRefFk, taxon);
311
					Taxon misappliedNameTaxon = null;
312
					if (misappliedTaxonId != null){
313
						TaxonBase<?> misTaxonBase =  taxonMap.get(String.valueOf(misappliedTaxonId));
314
						if (misTaxonBase == null){
315
							logger.warn("MisappliedName not found for misappliedTaxonId " + misappliedTaxonId + "; commonNameId: " + commonNameId);
316
						}else if (misTaxonBase.isInstanceOf(Taxon.class)){
317
							misappliedNameTaxon = CdmBase.deproxy(misTaxonBase, Taxon.class);
318
						}else{
319
							logger.warn("Misapplied name taxon is not of type Taxon but " + misTaxonBase.getClass().getSimpleName());
320
						}
321
					}else{
322

    
323
						Reference sec = refMap.get(String.valueOf(misNameRefFk));
324
						if (nameUsedInSource == null || sec == null){
325
							logger.warn("Taxon name or misapplied name reference is null for common name " + commonNameId);
326
						}else{
327
							misappliedNameTaxon = Taxon.NewInstance(nameUsedInSource, sec);
328
							MarkerType misCommonNameMarker = getMarkerType(state, BerlinModelTransformer.uuidMisappliedCommonName,"Misapplied Common Name in Berlin Model", "Misapplied taxon was automatically created by Berlin Model import for a common name with a misapplied name reference", "MCN");
329
							Marker marker = Marker.NewInstance(misCommonNameMarker, true);
330
							misappliedNameTaxon.addMarker(marker);
331
							taxaToSave.add(misappliedNameTaxon);
332
							logger.warn("Misapplied name taxon could not be found in database but misapplied name reference exists for common name. " +
333
									"New misapplied name for misapplied reference common name was added. CommonNameId: " + commonNameId);
334
						}
335
					}
336
					if (misappliedNameTaxon != null){
337

    
338
						if (! taxon.getMisappliedNames(false).contains(misappliedNameTaxon)){
339
							taxon.addMisappliedName(misappliedNameTaxon,state.getTransactionalSourceReference(), null);
340
							logger.warn("Misapplied name for common name was not found related to the accepted taxon. Created new relationship. CommonNameId: " + commonNameId);
341
						}
342

    
343
						TaxonDescription misappliedNameDescription = getDescription(misappliedNameTaxon);
344
						for (CommonTaxonName commonTaxonName : commonTaxonNames){
345
							CommonTaxonName commonNameClone = (CommonTaxonName)commonTaxonName.clone();
346
							misappliedNameDescription.addElement(commonNameClone);
347
						}
348
					}else{
349
						//wird schon oben gelogged
350
					    //logger.warn("Misapplied name is null for common name " + commonNameId);
351
					}
352

    
353
				}
354

    
355

    
356
				//reference extensions
357
				if (reference != null){
358
					if (StringUtils.isNotBlank(refLanguage)){
359
						ExtensionType refLanguageExtensionType = getExtensionType( state, REFERENCE_LANGUAGE_STRING_UUID, "reference language","The language of the reference","ref. lang.");
360
						Extension.NewInstance(reference, refLanguage, refLanguageExtensionType);
361
					}
362

    
363
					if (StringUtils.isNotBlank(refLanguageIso639_2)){
364
						ExtensionType refLanguageIsoExtensionType = getExtensionType( state, REFERENCE_LANGUAGE_ISO639_2_UUID, "reference language iso 639-2","The iso 639-2 code of the references language","ref. lang. 639-2");
365
						Extension.NewInstance(reference, refLanguageIso639_2, refLanguageIsoExtensionType);
366
					}
367
				}else if (isNotBlank(refLanguage) || isNotBlank(refLanguageIso639_2)){
368
					logger.warn("Reference is null (" + languageRefRefFk + ") but refLanguage (" + CdmUtils.Nz(refLanguage) + ") or iso639_2 (" + CdmUtils.Nz(refLanguageIso639_2) + ") was not null for common name ("+ commonNameId +")");
369
				}
370

    
371
				//status
372
				if (isNotBlank(status)){
373
					AnnotationType statusAnnotationType = getAnnotationType( state, STATUS_ANNOTATION_UUID, "status","The status of this object","status", null);
374
					for (CommonTaxonName commonTaxonName : commonTaxonNames){
375
						Annotation annotation = Annotation.NewInstance(status, statusAnnotationType, Language.DEFAULT());
376
						commonTaxonName.addAnnotation(annotation);
377
					}
378
				}
379

    
380
				//Notes
381
				for (CommonTaxonName commonTaxonName : commonTaxonNames){
382
					doIdCreatedUpdatedNotes(state, commonTaxonName, rs, String.valueOf(commonNameId), NAMESPACE);
383
				}
384
				partitioner.startDoSave();
385
				taxaToSave.add(taxon);
386

    
387
			}
388
		} catch (SQLException e) {
389
			logger.error("SQLException:" +  e);
390
			return false;
391
		} catch (ClassCastException e) {
392
			e.printStackTrace();
393
		} catch (Exception e) {
394
            throw e;
395
        }
396

    
397
		//	logger.info( i + " names handled");
398
		getTaxonService().save(taxaToSave);
399
		return success;
400

    
401
	}
402

    
403
	/**
404
	 * @param iso6392Map
405
	 * @param iso639_2
406
	 * @param languageString
407
	 * @param originalLanguageString
408
	 * @param state
409
	 * @return
410
	 */
411
	private Language getAndHandleLanguage(Map<String, Language> iso639Map,	String iso639_2, String iso639_1, String languageString, String originalLanguageString, BerlinModelImportState state) {
412
		Language language;
413
		if (isNotBlank(iso639_2)|| isNotBlank(iso639_1)  ){
414
			//TODO test performance, implement in state
415
			language = getLanguageFromIsoMap(iso639Map, iso639_2, iso639_1);
416

    
417
			if (language == null){
418
				language = getTermService().getLanguageByIso(iso639_2);
419
				iso639Map.put(iso639_2, language);
420
				if (language == null){
421
					try {
422
						language = getTermService().getLanguageByIso(iso639_1);
423
					} catch (Exception e) {
424
						// TODO Auto-generated catch block
425
						// TODO remove if problem with duplicate DescElement_Annot id is solved
426
						e.printStackTrace();
427
					}
428
					iso639Map.put(iso639_1, language);
429
				}
430
				if (language == null){
431
					logger.warn("Language for code ISO693-2 '" + iso639_2 + "' and ISO693-1 '" + iso639_1 + "' was not found");
432
				}
433
			}
434
		} else if ("unknown".equals(languageString)){
435
			language = Language.UNKNOWN_LANGUAGE();
436
		} else if ("Majorcan".equalsIgnoreCase(languageString)){
437
			language = getLanguage(state, BerlinModelTransformer.uuidLangMajorcan, "Majorcan", "Majorcan (original 'mallorqu\u00EDn')", null);
438
		}else{
439
			logger.warn("language ISO 639_1 and ISO 639_2 were empty for " + languageString);
440
			language = null;
441
		}
442
		addOriginalLanguage(language, originalLanguageString);
443
		return language;
444
	}
445

    
446

    
447
	/**
448
	 * @param iso639Map
449
	 * @param iso639_2
450
	 * @param iso639_1
451
	 * @return
452
	 */
453
	private Language getLanguageFromIsoMap(Map<String, Language> iso639Map,	String iso639_2, String iso639_1) {
454
		Language language;
455
		language = iso639Map.get(iso639_2);
456
		if (language == null){
457
			language = iso639Map.get(iso639_1);
458
		}
459
		return language;
460
	}
461

    
462
	/**
463
	 * @param language
464
	 * @param originalLanguageString
465
	 */
466
	private void addOriginalLanguage(Language language,	String originalLanguageString) {
467
		if (isBlank(originalLanguageString)){
468
			return;
469
		}else if (language == null){
470
			logger.warn("Language could not be defined, but originalLanguageString exists: " + originalLanguageString);
471
		}else {
472
			Representation representation = language.getRepresentation(language);
473
			if (representation == null){
474
				language.addRepresentation(Representation.NewInstance(originalLanguageString, originalLanguageString, originalLanguageString, language));
475
				getTermService().saveOrUpdate(language);
476
			}
477
		}
478

    
479
	}
480

    
481

    
482

    
483
	/**
484
	 * Fills the regionFks with all regionFks from emCommonName. Comma separated regionFks will be split.
485
	 * @param state
486
	 * @param regionFks
487
	 * @param source
488
	 * @return
489
	 * @throws SQLException
490
	 *
491
	 */
492
	private void getRegionFks(BerlinModelImportState state, SortedSet<Integer> regionFks, Source source) throws SQLException {
493
		String sql = " SELECT DISTINCT RegionFks FROM emCommonName";
494
		if (state.getConfig().getCommonNameFilter() != null){
495
			sql += " WHERE " + state.getConfig().getCommonNameFilter();
496
		}
497

    
498
		ResultSet rs = source.getResultSet(sql);
499
		while (rs.next()){
500
			String strRegionFks = rs.getString("RegionFks");
501
			if (isBlank(strRegionFks)){
502
				continue;
503
			}
504

    
505
			String[] regionFkArray = strRegionFks.split(",");
506
			for (String regionFk: regionFkArray){
507
				regionFk = regionFk.trim();
508
				if (! StringUtils.isNumeric(regionFk) || "".equals(regionFk)  ){
509
					state.setUnsuccessfull();
510
					logger.warn("RegionFk is not numeric: " + regionFk +  " ( part of " + strRegionFks + ")");
511
				}else{
512
					regionFks.add(Integer.valueOf(regionFk));
513
				}
514
			}
515
		}
516
		return;
517
	}
518

    
519

    
520

    
521
	/**
522
	 * Fills the {@link #regionMap} by all emLanguageRegion regions defined in the sql filter.
523
	 * {@link #regionMap} maps emLanguageRegion.RegionId to named areas.
524
	 * @param state
525
	 * @param sqlWhere
526
	 * @param emTdwgMap
527
	 * @throws SQLException
528
	 */
529
	private void fillRegionMap(BerlinModelImportState state, String sqlWhere,
530
			Map<String, String> emTdwgMap) throws SQLException {
531
		Source source = state.getConfig().getSource();
532
		String sql;
533
		ResultSet rs;
534
		sql = " SELECT RegionId, Region FROM emLanguageRegion WHERE RegionId IN ("+ sqlWhere+ ") ";
535
		rs = source.getResultSet(sql);
536
		while (rs.next()){
537
			Object regionId = rs.getObject("RegionId");
538
			String region = rs.getString("Region");
539
			String[] splitRegion = region.split("-");
540
			if (splitRegion.length <= 1){
541
				NamedArea newArea = getNamedArea(state, null, region, "Language region '" + region + "'", null, null, null);
542
//				getTermService().save(newArea);
543
				regionMap.put(String.valueOf(regionId), newArea);
544
				logger.info("Found new area: " +  region);
545
			}else if (splitRegion.length == 2){
546
				String emCode = splitRegion[1].trim();
547
				String tdwgCode = emTdwgMap.get(emCode);
548
				if (isNotBlank(tdwgCode) ){
549
					NamedArea tdwgArea = getNamedArea(state, tdwgCode);
550
					regionMap.put(String.valueOf(regionId), tdwgArea);
551
				}else {
552
					NamedArea area = getOtherAreas(state, emCode, tdwgCode);
553
					if (area != null){
554
						regionMap.put(String.valueOf(regionId), area);
555
					}else{
556
						logger.warn("emCode did not map to valid tdwgCode: " +  CdmUtils.Nz(emCode) + "->" + CdmUtils.Nz(tdwgCode));
557
					}
558
				}
559
			}
560
		}
561
	}
562

    
563

    
564
	/**
565
	 * Returns the are for a given TDWG code. See {@link #getEmTdwgMap(Source)} for exceptions from
566
	 * the TDWG code
567
	 * @param state
568
	 * @param tdwgCode
569
	 */
570
	private NamedArea getNamedArea(BerlinModelImportState state, String tdwgCode) {
571
		NamedArea area;
572
		if (tdwgCode.equalsIgnoreCase("Ab")){
573
			area = getNamedArea(state, BerlinModelTransformer.uuidAb, "Azerbaijan & Nakhichevan", "Azerbaijan (including Nakhichevan)",  "Ab", null, null);
574
			getTermService().saveOrUpdate(area);
575
		}else if (tdwgCode.equalsIgnoreCase("Uk")){
576
			area = getNamedArea(state, BerlinModelTransformer.uuidUk , "Ukraine & Crimea", "Ukraine (including Crimea)", "Uk", null, null);
577
			getTermService().saveOrUpdate(area);
578
		}else if (tdwgCode.equalsIgnoreCase("Rf")){
579
//			area = getNamedArea(state, BerlinModelTransformer.uuidRf , "Ukraine & Crimea", "Ukraine (including Crimea)", "Uk", null, null);
580
//			getTermService().saveOrUpdate(area);
581
			area = Country.RUSSIANFEDERATION();
582
		}else if (tdwgCode.equalsIgnoreCase("Gg")){
583
			area = Country.GEORGIA();
584
		}else if (tdwgCode.equalsIgnoreCase("SM")){
585
            area = getNamedArea(state, BerlinModelTransformer.uuidSM , "Serbia & Montenegro", "Serbia & Montenegro", "SM", null, null);
586
            getTermService().saveOrUpdate(area);
587
        }else if (tdwgCode.equalsIgnoreCase("Tu")){
588
            area = Country.TURKEYREPUBLICOF();
589
        }else{
590
			area = TdwgAreaProvider.getAreaByTdwgAbbreviation(tdwgCode);
591
		}
592
		if (area == null){
593
			logger.warn("Area is null for " + tdwgCode);
594
		}
595
		return area;
596
	}
597

    
598
	/**
599
	 * @param regionFks
600
	 * @return
601
	 */
602
	private String getSqlWhere(SortedSet<Integer> regionFks) {
603
		String sqlWhere = "";
604
		for (Integer regionFk : regionFks){
605
			sqlWhere += regionFk + ",";
606
		}
607
		sqlWhere = sqlWhere.substring(0, sqlWhere.length()-1);
608
		return sqlWhere;
609
	}
610

    
611
	/**
612
	 * Returns a map which is filled by the emCode->TdwgCode mapping defined in emArea.
613
	 * Some exceptions are defined for emCode 'Ab','Rf','Uk' and some additional mapping is added
614
	 * for 'Ab / Ab(A)', 'Ga / Ga(F)', 'It / It(I)', 'Ar / Ar(A)','Hs / Hs(S)'
615
	 * @param source
616
	 * @throws SQLException
617
	 */
618
	private Map<String, String> getEmTdwgMap(Source source) throws SQLException {
619
		String sql;
620
		ResultSet rs;
621
		Map<String, String> emTdwgMap = new HashMap<>();
622
		sql = " SELECT EmCode, TDWGCode FROM emArea ";
623
		rs = source.getResultSet(sql);
624
		while (rs.next()){
625
			String emCode = rs.getString("EMCode");
626
			String TDWGCode = rs.getString("TDWGCode");
627
			if (isNotBlank(emCode) ){
628
				emCode = emCode.trim();
629
				if (emCode.equalsIgnoreCase("Ab") || emCode.equalsIgnoreCase("Rf")||
630
						emCode.equalsIgnoreCase("Uk") || emCode.equalsIgnoreCase("Gg")
631
						|| emCode.equalsIgnoreCase("SM") || emCode.equalsIgnoreCase("Tu")){
632
					emTdwgMap.put(emCode, emCode);
633
				}else if (isNotBlank(TDWGCode)){
634
					emTdwgMap.put(emCode, TDWGCode.trim());
635
				}
636
			}
637
		}
638
		emTdwgMap.put("Ab / Ab(A)", "Ab");
639
		emTdwgMap.put("Ga / Ga(F)", "FRA-FR");
640
		emTdwgMap.put("It / It(I)", "ITA");
641
		emTdwgMap.put("Uk / Uk(U)", "Uk");
642
		emTdwgMap.put("Ar / Ar(A)", "TCS-AR");
643
		emTdwgMap.put("Hs / Hs(S)", "SPA-SP");
644
		emTdwgMap.put("Hb / Hb(E)", "IRE-IR");
645

    
646
		return emTdwgMap;
647
	}
648

    
649

    
650
	/**
651
	 * Returns the first non-image gallery description. Creates a new one if no description exists.
652
	 * @param taxon
653
	 * @return
654
	 */
655
	private TaxonDescription getDescription(Taxon taxon) {
656
		TaxonDescription result = null;
657
		for (TaxonDescription taxonDescription : taxon.getDescriptions()){
658
			if (! taxonDescription.isImageGallery()){
659
				result = taxonDescription;
660
			}
661
		}
662
		if (result == null){
663
			result = TaxonDescription.NewInstance(taxon);
664
		}
665
		return result;
666
	}
667

    
668
	@Override
669
	public Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForPartition(ResultSet rs, BerlinModelImportState state) {
670
		String nameSpace;
671
		Class<?> cdmClass;
672
		Set<String> idSet;
673
		Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<>();
674

    
675
		String pos = "0";
676
		try{
677
			Set<String> taxonIdSet = new HashSet<>();
678
			Set<String> nameIdSet = new HashSet<>();
679
			Set<String> referenceIdSet = new HashSet<>();
680
			while (rs.next()){
681
				handleForeignKey(rs, taxonIdSet, "taxonId");
682
				handleForeignKey(rs, taxonIdSet, "factTaxonId");
683
                handleForeignKey(rs, taxonIdSet, "misappliedTaxonId");
684
				handleForeignKey(rs, referenceIdSet, "refId");
685
				handleForeignKey(rs, referenceIdSet, "languageRefRefFk");
686
				handleForeignKey(rs, nameIdSet, "NameInSourceFk");
687
				handleForeignKey(rs, nameIdSet, "PTNameFk");
688
				handleForeignKey(rs, referenceIdSet, "MisNameRefFk");
689
			}
690

    
691
			//name map
692
			nameSpace = BerlinModelTaxonNameImport.NAMESPACE;
693
			cdmClass = TaxonName.class;
694
			idSet = nameIdSet;
695
			@SuppressWarnings("unchecked")
696
            Map<String, TaxonName> nameMap = (Map<String, TaxonName>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
697
			result.put(nameSpace, nameMap);
698

    
699
			//taxon map
700
			nameSpace = BerlinModelTaxonImport.NAMESPACE;
701
			cdmClass = TaxonBase.class;
702
			idSet = taxonIdSet;
703
			@SuppressWarnings("unchecked")
704
            Map<String, TaxonBase<?>> taxonMap = (Map<String, TaxonBase<?>>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
705
			result.put(nameSpace, taxonMap);
706

    
707
			//reference map
708
			nameSpace = BerlinModelReferenceImport.REFERENCE_NAMESPACE;
709
			cdmClass = Reference.class;
710
			idSet = referenceIdSet;
711
			@SuppressWarnings("unchecked")
712
            Map<String, Reference> referenceMap = (Map<String, Reference>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
713
			result.put(nameSpace, referenceMap);
714
			// TODO remove if problem with duplicate DescElement_Annot id is solved
715
		} catch (SQLException e) {
716
			throw new RuntimeException("pos: " +pos, e);
717
		} catch (NullPointerException nep){
718
			logger.error("NullPointerException in getRelatedObjectsForPartition()");
719
		}
720
		return result;
721
	}
722

    
723

    
724
	@Override
725
	protected boolean doCheck(BerlinModelImportState state){
726
		IOValidator<BerlinModelImportState> validator = new BerlinModelCommonNamesImportValidator();
727
		return validator.validate(state);
728
	}
729

    
730

    
731
	@Override
732
	protected boolean isIgnore(BerlinModelImportState state){
733
		return ! state.getConfig().isDoCommonNames();
734
	}
735

    
736
}
(3-3/21)