Project

General

Profile

Download (30.2 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.CdmBase;
36
import eu.etaxonomy.cdm.model.common.Extension;
37
import eu.etaxonomy.cdm.model.common.ExtensionType;
38
import eu.etaxonomy.cdm.model.common.Language;
39
import eu.etaxonomy.cdm.model.common.Marker;
40
import eu.etaxonomy.cdm.model.common.MarkerType;
41
import eu.etaxonomy.cdm.model.common.Representation;
42
import eu.etaxonomy.cdm.model.description.CommonTaxonName;
43
import eu.etaxonomy.cdm.model.description.DescriptionElementSource;
44
import eu.etaxonomy.cdm.model.description.TaxonDescription;
45
import eu.etaxonomy.cdm.model.location.Country;
46
import eu.etaxonomy.cdm.model.location.NamedArea;
47
import eu.etaxonomy.cdm.model.name.TaxonName;
48
import eu.etaxonomy.cdm.model.reference.Reference;
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 BerlinModelCommonNamesImport  extends BerlinModelImportBase {
59
    private static final long serialVersionUID = -8921948187177864321L;
60

    
61
    private static final Logger logger = Logger.getLogger(BerlinModelCommonNamesImport.class);
62

    
63
	public static final UUID REFERENCE_LANGUAGE_ISO639_2_UUID = UUID.fromString("40c4f8dd-3d9c-44a4-b77a-76e137a89a5f");
64
	public static final UUID REFERENCE_LANGUAGE_STRING_UUID = UUID.fromString("2a1b678f-c27d-48c1-b43e-98fd0d426305");
65
	public static final UUID COMMONNAME_STATUS_RECOMMENDED_UUID = UUID.fromString("e3f7b80a-1286-458d-812c-5e818f731968");
66
	public static final UUID COMMONNAME_STATUS_SYNONYM_UUID = UUID.fromString("169b2d97-a706-49de-b28b-c67f0ee6764b");
67

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

    
70

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

    
74

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

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

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

    
90
		return result;
91
	}
92

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

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

    
121
		return recordQuery;
122
	}
123

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

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

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

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

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

    
168

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

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

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

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

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

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

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

    
211
				if (commonNameId == lastCommonNameId){
212
				    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. ");
213
				}else{
214
				    lastCommonNameId = commonNameId;
215
				}
216

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

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

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

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

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

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

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

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

    
306

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

    
322
						Reference sec = refMap.get(String.valueOf(misNameRefFk));
323
						if (nameUsedInSource == null || sec == null){
324
							logger.warn("Taxon name or misapplied name reference is null for common name " + commonNameId);
325
						}else{
326
							misappliedNameTaxon = Taxon.NewInstance(nameUsedInSource, sec);
327
							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");
328
							Marker marker = Marker.NewInstance(misCommonNameMarker, true);
329
							misappliedNameTaxon.addMarker(marker);
330
							taxaToSave.add(misappliedNameTaxon);
331
							logger.warn("Misapplied name taxon could not be found in database but misapplied name reference exists for common name. " +
332
									"New misapplied name for misapplied reference common name was added. CommonNameId: " + commonNameId);
333
						}
334
					}
335
					if (misappliedNameTaxon != null){
336

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

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

    
352
				}
353

    
354

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

    
362
					if (StringUtils.isNotBlank(refLanguageIso639_2)){
363
						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");
364
						Extension.NewInstance(reference, refLanguageIso639_2, refLanguageIsoExtensionType);
365
					}
366
				}else if (isNotBlank(refLanguage) || isNotBlank(refLanguageIso639_2)){
367
					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 +")");
368
				}
369

    
370
				//status
371
				if (isNotBlank(status)){
372
					MarkerType recommendedMarkerType = getMarkerType( state, COMMONNAME_STATUS_RECOMMENDED_UUID, "recommended","If the common name has the status recommended (see also status 'synonym', if none of them is true the default status is 'unassessed')","recommended", null);
373
					MarkerType synonymMarkerType = getMarkerType( state, COMMONNAME_STATUS_SYNONYM_UUID, "synonym","If the common name has the status synonym (see also status 'recommended', if none of them is true the default status is 'unassessed')","synonym", null);
374
                    for (CommonTaxonName commonTaxonName : commonTaxonNames){
375
                        Marker marker = null;
376
                        if (status.equals("recommended")){
377
						    marker = Marker.NewInstance(recommendedMarkerType, true);
378
                        }else if (status.equals("synonym")){
379
                            marker = Marker.NewInstance(synonymMarkerType, true);
380
                        }else if (status.equals("unassessed")){
381
                            //do nothing
382
                        }else{
383
						    logger.warn("Unknown common name status: " + status);
384
						}
385
                        if (marker != null){
386
                            commonTaxonName.addMarker(marker);
387
                        }
388
					}
389
				}
390

    
391
				//Notes
392
				for (CommonTaxonName commonTaxonName : commonTaxonNames){
393
					doIdCreatedUpdatedNotes(state, commonTaxonName, rs, String.valueOf(commonNameId), NAMESPACE);
394
				}
395
				partitioner.startDoSave();
396
				taxaToSave.add(taxon);
397

    
398
			}
399
		} catch (SQLException e) {
400
			logger.error("SQLException:" +  e);
401
			return false;
402
		} catch (ClassCastException e) {
403
			e.printStackTrace();
404
		} catch (Exception e) {
405
            throw e;
406
        }
407

    
408
		//	logger.info( i + " names handled");
409
		getTaxonService().save(taxaToSave);
410
		return success;
411

    
412
	}
413

    
414
	/**
415
	 * @param iso6392Map
416
	 * @param iso639_2
417
	 * @param languageString
418
	 * @param originalLanguageString
419
	 * @param state
420
	 * @return
421
	 */
422
	private Language getAndHandleLanguage(Map<String, Language> iso639Map,	String iso639_2, String iso639_1, String languageString, String originalLanguageString, BerlinModelImportState state) {
423
		Language language;
424
		if (isNotBlank(iso639_2)|| isNotBlank(iso639_1)  ){
425
			//TODO test performance, implement in state
426
			language = getLanguageFromIsoMap(iso639Map, iso639_2, iso639_1);
427

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

    
457

    
458
	/**
459
	 * @param iso639Map
460
	 * @param iso639_2
461
	 * @param iso639_1
462
	 * @return
463
	 */
464
	private Language getLanguageFromIsoMap(Map<String, Language> iso639Map,	String iso639_2, String iso639_1) {
465
		Language language;
466
		language = iso639Map.get(iso639_2);
467
		if (language == null){
468
			language = iso639Map.get(iso639_1);
469
		}
470
		return language;
471
	}
472

    
473
	/**
474
	 * @param language
475
	 * @param originalLanguageString
476
	 */
477
	private void addOriginalLanguage(Language language,	String originalLanguageString) {
478
		if (isBlank(originalLanguageString)){
479
			return;
480
		}else if (language == null){
481
			logger.warn("Language could not be defined, but originalLanguageString exists: " + originalLanguageString);
482
		}else {
483
			Representation representation = language.getRepresentation(language);
484
			if (representation == null){
485
				language.addRepresentation(Representation.NewInstance(originalLanguageString, originalLanguageString, originalLanguageString, language));
486
				getTermService().saveOrUpdate(language);
487
			}
488
		}
489

    
490
	}
491

    
492

    
493

    
494
	/**
495
	 * Fills the regionFks with all regionFks from emCommonName. Comma separated regionFks will be split.
496
	 * @param state
497
	 * @param regionFks
498
	 * @param source
499
	 * @return
500
	 * @throws SQLException
501
	 *
502
	 */
503
	private void getRegionFks(BerlinModelImportState state, SortedSet<Integer> regionFks, Source source) throws SQLException {
504
		String sql = " SELECT DISTINCT RegionFks FROM emCommonName";
505
		if (state.getConfig().getCommonNameFilter() != null){
506
			sql += " WHERE " + state.getConfig().getCommonNameFilter();
507
		}
508

    
509
		ResultSet rs = source.getResultSet(sql);
510
		while (rs.next()){
511
			String strRegionFks = rs.getString("RegionFks");
512
			if (isBlank(strRegionFks)){
513
				continue;
514
			}
515

    
516
			String[] regionFkArray = strRegionFks.split(",");
517
			for (String regionFk: regionFkArray){
518
				regionFk = regionFk.trim();
519
				if (! StringUtils.isNumeric(regionFk) || "".equals(regionFk)  ){
520
					state.setUnsuccessfull();
521
					logger.warn("RegionFk is not numeric: " + regionFk +  " ( part of " + strRegionFks + ")");
522
				}else{
523
					regionFks.add(Integer.valueOf(regionFk));
524
				}
525
			}
526
		}
527
		return;
528
	}
529

    
530

    
531

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

    
574

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

    
609
	/**
610
	 * @param regionFks
611
	 * @return
612
	 */
613
	private String getSqlWhere(SortedSet<Integer> regionFks) {
614
		String sqlWhere = "";
615
		for (Integer regionFk : regionFks){
616
			sqlWhere += regionFk + ",";
617
		}
618
		sqlWhere = sqlWhere.substring(0, sqlWhere.length()-1);
619
		return sqlWhere;
620
	}
621

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

    
657
		return emTdwgMap;
658
	}
659

    
660

    
661
	/**
662
	 * Returns the first non-image gallery description. Creates a new one if no description exists.
663
	 * @param taxon
664
	 * @return
665
	 */
666
	private TaxonDescription getDescription(Taxon taxon) {
667
		TaxonDescription result = null;
668
		for (TaxonDescription taxonDescription : taxon.getDescriptions()){
669
			if (! taxonDescription.isImageGallery()){
670
				result = taxonDescription;
671
			}
672
		}
673
		if (result == null){
674
			result = TaxonDescription.NewInstance(taxon);
675
		}
676
		return result;
677
	}
678

    
679
	@Override
680
	public Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForPartition(ResultSet rs, BerlinModelImportState state) {
681
		String nameSpace;
682
		Class<?> cdmClass;
683
		Set<String> idSet;
684
		Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<>();
685

    
686
		String pos = "0";
687
		try{
688
			Set<String> taxonIdSet = new HashSet<>();
689
			Set<String> nameIdSet = new HashSet<>();
690
			Set<String> referenceIdSet = new HashSet<>();
691
			while (rs.next()){
692
				handleForeignKey(rs, taxonIdSet, "taxonId");
693
				handleForeignKey(rs, taxonIdSet, "factTaxonId");
694
                handleForeignKey(rs, taxonIdSet, "misappliedTaxonId");
695
				handleForeignKey(rs, referenceIdSet, "refId");
696
				handleForeignKey(rs, referenceIdSet, "languageRefRefFk");
697
				handleForeignKey(rs, nameIdSet, "NameInSourceFk");
698
				handleForeignKey(rs, nameIdSet, "PTNameFk");
699
				handleForeignKey(rs, referenceIdSet, "MisNameRefFk");
700
			}
701

    
702
			//name map
703
			nameSpace = BerlinModelTaxonNameImport.NAMESPACE;
704
			cdmClass = TaxonName.class;
705
			idSet = nameIdSet;
706
			@SuppressWarnings("unchecked")
707
            Map<String, TaxonName> nameMap = (Map<String, TaxonName>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
708
			result.put(nameSpace, nameMap);
709

    
710
			//taxon map
711
			nameSpace = BerlinModelTaxonImport.NAMESPACE;
712
			cdmClass = TaxonBase.class;
713
			idSet = taxonIdSet;
714
			@SuppressWarnings("unchecked")
715
            Map<String, TaxonBase<?>> taxonMap = (Map<String, TaxonBase<?>>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
716
			result.put(nameSpace, taxonMap);
717

    
718
			//reference map
719
			nameSpace = BerlinModelReferenceImport.REFERENCE_NAMESPACE;
720
			cdmClass = Reference.class;
721
			idSet = referenceIdSet;
722
			@SuppressWarnings("unchecked")
723
            Map<String, Reference> referenceMap = (Map<String, Reference>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
724
			result.put(nameSpace, referenceMap);
725
			// TODO remove if problem with duplicate DescElement_Annot id is solved
726
		} catch (SQLException e) {
727
			throw new RuntimeException("pos: " +pos, e);
728
		} catch (NullPointerException nep){
729
			logger.error("NullPointerException in getRelatedObjectsForPartition()");
730
		}
731
		return result;
732
	}
733

    
734

    
735
	@Override
736
	protected boolean doCheck(BerlinModelImportState state){
737
		IOValidator<BerlinModelImportState> validator = new BerlinModelCommonNamesImportValidator();
738
		return validator.validate(state);
739
	}
740

    
741

    
742
	@Override
743
	protected boolean isIgnore(BerlinModelImportState state){
744
		return ! state.getConfig().isDoCommonNames();
745
	}
746

    
747
}
(3-3/21)