Project

General

Profile

Download (31.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.common.TermType;
43
import eu.etaxonomy.cdm.model.common.TermVocabulary;
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 COMMONNAME_STATUS_RECOMMENDED_UUID = UUID.fromString("e3f7b80a-1286-458d-812c-5e818f731968");
68
	public static final UUID COMMONNAME_STATUS_SYNONYM_UUID = UUID.fromString("169b2d97-a706-49de-b28b-c67f0ee6764b");
69

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

    
72

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

    
76

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

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

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

    
92
		return result;
93
	}
94

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

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

    
123
		return recordQuery;
124
	}
125

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

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

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

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

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

    
170

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

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

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

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

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

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

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

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

    
219
				final String NO_REGION = "";
220
				//regions
221
				String regionFks  = rs.getString("RegionFks");
222
				String[] regionFkSplit = (regionFks==null)? new String[]{NO_REGION} : regionFks.trim().split(",");
223
				if (regionFkSplit.length == 0){
224
				    String message = "regionFkSplit should never be empty but was for common name id " + commonNameId;
225
                    logger.warn(message);
226
				}
227

    
228
				//commonNameString
229
				if (isBlank(commonNameString)){
230
					String message = "CommonName is empty or null. Do not import record for taxon " + taxonId;
231
					logger.warn(message);
232
					continue;
233
				}
234

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

    
259
				//Language
260
				Language language = getAndHandleLanguage(iso6392Map, iso639_2, iso639_1, languageString, originalLanguageString, state);
261

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

    
287
				//Reference/Source
288
				if (! CdmUtils.nullSafeEqual(refId, languageRefRefFk)){
289
					//use strRefId if languageRefFk is null
290
					if (languageRefRefFk == null){
291
						languageRefRefFk = refId;
292
					}else{
293
						logger.warn("CommonName.RefFk (" + CdmUtils.Nz(refId) + ") and LanguageReference.RefFk " + languageRefRefFk  + " are not equal. I will import only languageReference.RefFk");
294
					}
295
				}
296

    
297
				Reference reference = refMap.get(String.valueOf(languageRefRefFk));
298
				if (reference == null && languageRefRefFk != null){
299
					logger.warn("CommonName reference was null but reference exists. languageRefRefFk = " + languageRefRefFk + "; commonNameId = " + commonNameId);
300
				}
301
				String microCitation = null;
302
				String originalNameString = null;
303

    
304
				TaxonName nameUsedInSource = taxonNameMap.get(String.valueOf(nameInSourceFk));
305
				if (nameInSourceFk != null && nameUsedInSource == null){
306
					if (nameInSourceFk != -1 || !state.getConfig().isEuroMed()){
307
					    logger.warn("Name used in source (" + nameInSourceFk + ") was not found for common name " + commonNameId);
308
					}
309
				}
310
				for (CommonTaxonName commonTaxonName : commonTaxonNames){
311
				    DescriptionElementSource source = DescriptionElementSource.NewPrimarySourceInstance(reference, microCitation, nameUsedInSource, originalNameString);
312
	                commonTaxonName.addSource(source);
313
				}
314

    
315

    
316
				//MisNameRef
317
				if (misNameRefFk != null){
318
					//Taxon misappliedName = getMisappliedName(biblioRefMap, nomRefMap, misNameRefFk, taxon);
319
					Taxon misappliedNameTaxon = null;
320
					if (misappliedTaxonId != null){
321
						TaxonBase<?> misTaxonBase =  taxonMap.get(String.valueOf(misappliedTaxonId));
322
						if (misTaxonBase == null){
323
							logger.warn("MisappliedName not found for misappliedTaxonId " + misappliedTaxonId + "; commonNameId: " + commonNameId);
324
						}else if (misTaxonBase.isInstanceOf(Taxon.class)){
325
							misappliedNameTaxon = CdmBase.deproxy(misTaxonBase, Taxon.class);
326
						}else{
327
							logger.warn("Misapplied name taxon is not of type Taxon but " + misTaxonBase.getClass().getSimpleName());
328
						}
329
					}else{
330

    
331
						Reference sec = refMap.get(String.valueOf(misNameRefFk));
332
						if (nameUsedInSource == null || sec == null){
333
							logger.warn("Taxon name or misapplied name reference is null for common name " + commonNameId);
334
						}else{
335
							misappliedNameTaxon = Taxon.NewInstance(nameUsedInSource, sec);
336
							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");
337
							Marker marker = Marker.NewInstance(misCommonNameMarker, true);
338
							misappliedNameTaxon.addMarker(marker);
339
							taxaToSave.add(misappliedNameTaxon);
340
							logger.warn("Misapplied name taxon could not be found in database but misapplied name reference exists for common name. " +
341
									"New misapplied name for misapplied reference common name was added. CommonNameId: " + commonNameId);
342
						}
343
					}
344
					if (misappliedNameTaxon != null){
345

    
346
						if (! taxon.getMisappliedNames(false).contains(misappliedNameTaxon)){
347
							taxon.addMisappliedName(misappliedNameTaxon, state.getTransactionalSourceReference(), null);
348
							logger.warn("Misapplied name for common name was not found related to the accepted taxon. Created new relationship. CommonNameId: " + commonNameId);
349
						}
350

    
351
						//add common name also to missaplied taxon
352
						//TODO is this really wanted
353
						TaxonDescription misappliedNameDescription = getDescription(misappliedNameTaxon);
354
						for (CommonTaxonName commonTaxonName : commonTaxonNames){
355
							CommonTaxonName commonNameClone = (CommonTaxonName)commonTaxonName.clone();
356
							misappliedNameDescription.addElement(commonNameClone);
357
							doIdCreatedUpdatedNotes(state, commonNameClone, rs, String.valueOf(commonNameId), NAMESPACE);
358
						}
359
					}else{
360
						//wird schon oben gelogged
361
					    //logger.warn("Misapplied name is null for common name " + commonNameId);
362
					}
363

    
364
				}
365

    
366
				//reference extensions
367
				if (reference != null){
368
					if (isNotBlank(refLanguage) && !reference.hasExtension(REFERENCE_LANGUAGE_STRING_UUID, refLanguage)){
369
						ExtensionType refLanguageExtensionType = getExtensionType( state, REFERENCE_LANGUAGE_STRING_UUID, "reference language","The language of the reference","ref. lang.");
370
						Extension.NewInstance(reference, refLanguage, refLanguageExtensionType);
371
					}
372

    
373
					if (isNotBlank(refLanguageIso639_2) && !reference.hasExtension(REFERENCE_LANGUAGE_ISO639_2_UUID, refLanguage)){
374
						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");
375
						Extension.NewInstance(reference, refLanguageIso639_2, refLanguageIsoExtensionType);
376
					}
377
				}else if (isNotBlank(refLanguage) || isNotBlank(refLanguageIso639_2)){
378
					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 +")");
379
				}
380

    
381
				//status
382
				if (isNotBlank(status)){
383
				    TermVocabulary<MarkerType> markerTypeVoc = getVocabulary(TermType.MarkerType, BerlinModelTransformer.uuidVocEMMarkerType,
384
				            "Euro+Med marker type vocabulary", "E+M marker types", null, null, false, MarkerType.COMPLETE());
385
				    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')",
386
				            "recommended", markerTypeVoc);
387
					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')",
388
					        "synonym", markerTypeVoc);
389
                    for (CommonTaxonName commonTaxonName : commonTaxonNames){
390
                        Marker marker = null;
391
                        if (status.equals("recommended")){
392
						    marker = Marker.NewInstance(recommendedMarkerType, true);
393
                        }else if (status.equals("synonym")){
394
                            marker = Marker.NewInstance(synonymMarkerType, true);
395
                        }else if (status.equals("unassessed")){
396
                            //do nothing
397
                        }else{
398
						    logger.warn("Unknown common name status: " + status);
399
						}
400
                        if (marker != null){
401
                            commonTaxonName.addMarker(marker);
402
                        }
403
					}
404
				}
405

    
406
				//Notes
407
				for (CommonTaxonName commonTaxonName : commonTaxonNames){
408
					doIdCreatedUpdatedNotes(state, commonTaxonName, rs, String.valueOf(commonNameId), NAMESPACE);
409
				}
410
				partitioner.startDoSave();
411
				taxaToSave.add(taxon);
412

    
413
			}
414
		} catch (SQLException e) {
415
			logger.error("SQLException:" +  e);
416
			return false;
417
		} catch (ClassCastException e) {
418
			e.printStackTrace();
419
		} catch (Exception e) {
420
            throw e;
421
        }
422

    
423
		//	logger.info( i + " names handled");
424
		getTaxonService().save(taxaToSave);
425
		return success;
426

    
427
	}
428

    
429
    /**
430
	 * @param iso6392Map
431
	 * @param iso639_2
432
	 * @param languageString
433
	 * @param originalLanguageString
434
	 * @param state
435
	 * @return
436
	 */
437
	private Language getAndHandleLanguage(Map<String, Language> iso639Map,	String iso639_2, String iso639_1, String languageString, String originalLanguageString, BerlinModelImportState state) {
438
		Language language;
439
		if (isNotBlank(iso639_2)|| isNotBlank(iso639_1)  ){
440
			//TODO test performance, implement in state
441
			language = getLanguageFromIsoMap(iso639Map, iso639_2, iso639_1);
442

    
443
			if (language == null){
444
				language = getTermService().getLanguageByIso(iso639_2);
445
				iso639Map.put(iso639_2, language);
446
				if (language == null){
447
					try {
448
						language = getTermService().getLanguageByIso(iso639_1);
449
					} catch (Exception e) {
450
						// TODO Auto-generated catch block
451
						// TODO remove if problem with duplicate DescElement_Annot id is solved
452
						e.printStackTrace();
453
					}
454
					iso639Map.put(iso639_1, language);
455
				}
456
				if (language == null){
457
					logger.warn("Language for code ISO693-2 '" + iso639_2 + "' and ISO693-1 '" + iso639_1 + "' was not found");
458
				}
459
			}
460
		} else if ("unknown".equals(languageString)){
461
			language = Language.UNKNOWN_LANGUAGE();
462
		} else if ("Majorcan".equalsIgnoreCase(languageString)){
463
			language = getLanguage(state, BerlinModelTransformer.uuidLangMajorcan, "Majorcan", "Majorcan (original 'mallorqu\u00EDn')", null);
464
		}else{
465
			logger.warn("language ISO 639_1 and ISO 639_2 were empty for " + languageString);
466
			language = null;
467
		}
468
		addOriginalLanguage(language, originalLanguageString);
469
		return language;
470
	}
471

    
472

    
473
	/**
474
	 * @param iso639Map
475
	 * @param iso639_2
476
	 * @param iso639_1
477
	 * @return
478
	 */
479
	private Language getLanguageFromIsoMap(Map<String, Language> iso639Map,	String iso639_2, String iso639_1) {
480
		Language language;
481
		language = iso639Map.get(iso639_2);
482
		if (language == null){
483
			language = iso639Map.get(iso639_1);
484
		}
485
		return language;
486
	}
487

    
488
	/**
489
	 * @param language
490
	 * @param originalLanguageString
491
	 */
492
	private void addOriginalLanguage(Language language,	String originalLanguageString) {
493
		if (isBlank(originalLanguageString)){
494
			return;
495
		}else if (language == null){
496
			logger.warn("Language could not be defined, but originalLanguageString exists: " + originalLanguageString);
497
		}else {
498
			Representation representation = language.getRepresentation(language);
499
			if (representation == null){
500
				language.addRepresentation(Representation.NewInstance(originalLanguageString, originalLanguageString, originalLanguageString, language));
501
				getTermService().saveOrUpdate(language);
502
			}
503
		}
504

    
505
	}
506

    
507

    
508

    
509
	/**
510
	 * Fills the regionFks with all regionFks from emCommonName. Comma separated regionFks will be split.
511
	 * @param state
512
	 * @param regionFks
513
	 * @param source
514
	 * @return
515
	 * @throws SQLException
516
	 *
517
	 */
518
	private void getRegionFks(BerlinModelImportState state, SortedSet<Integer> regionFks, Source source) throws SQLException {
519
		String sql = " SELECT DISTINCT RegionFks FROM emCommonName";
520
		if (state.getConfig().getCommonNameFilter() != null){
521
			sql += " WHERE " + state.getConfig().getCommonNameFilter();
522
		}
523

    
524
		ResultSet rs = source.getResultSet(sql);
525
		while (rs.next()){
526
			String strRegionFks = rs.getString("RegionFks");
527
			if (isBlank(strRegionFks)){
528
				continue;
529
			}
530

    
531
			String[] regionFkArray = strRegionFks.split(",");
532
			for (String regionFk: regionFkArray){
533
				regionFk = regionFk.trim();
534
				if (! StringUtils.isNumeric(regionFk) || "".equals(regionFk)  ){
535
					state.setUnsuccessfull();
536
					logger.warn("RegionFk is not numeric: " + regionFk +  " ( part of " + strRegionFks + ")");
537
				}else{
538
					regionFks.add(Integer.valueOf(regionFk));
539
				}
540
			}
541
		}
542
		return;
543
	}
544

    
545

    
546

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

    
589

    
590
	/**
591
	 * Returns the are for a given TDWG code. See {@link #getEmTdwgMap(Source)} for exceptions from
592
	 * the TDWG code
593
	 * @param state
594
	 * @param tdwgCode
595
	 */
596
	private NamedArea getNamedArea(BerlinModelImportState state, String tdwgCode) {
597
		NamedArea area;
598
		if (tdwgCode.equalsIgnoreCase("Ab")){
599
			area = getNamedArea(state, BerlinModelTransformer.uuidAb, "Azerbaijan & Nakhichevan", "Azerbaijan (including Nakhichevan)",  "Ab", null, null);
600
			getTermService().saveOrUpdate(area);
601
		}else if (tdwgCode.equalsIgnoreCase("Uk")){
602
			area = getNamedArea(state, BerlinModelTransformer.uuidUk , "Ukraine & Crimea", "Ukraine (including Crimea)", "Uk", null, null);
603
			getTermService().saveOrUpdate(area);
604
		}else if (tdwgCode.equalsIgnoreCase("Rf")){
605
//			area = getNamedArea(state, BerlinModelTransformer.uuidRf , "Ukraine & Crimea", "Ukraine (including Crimea)", "Uk", null, null);
606
//			getTermService().saveOrUpdate(area);
607
			area = Country.RUSSIANFEDERATION();
608
		}else if (tdwgCode.equalsIgnoreCase("Gg")){
609
			area = Country.GEORGIA();
610
		}else if (tdwgCode.equalsIgnoreCase("SM")){
611
            area = getNamedArea(state, BerlinModelTransformer.uuidSM , "Serbia & Montenegro", "Serbia & Montenegro", "SM", null, null);
612
            getTermService().saveOrUpdate(area);
613
        }else if (tdwgCode.equalsIgnoreCase("Tu")){
614
            area = Country.TURKEYREPUBLICOF();
615
        }else{
616
			area = TdwgAreaProvider.getAreaByTdwgAbbreviation(tdwgCode);
617
		}
618
		if (area == null){
619
			logger.warn("Area is null for " + tdwgCode);
620
		}
621
		return area;
622
	}
623

    
624
	/**
625
	 * @param regionFks
626
	 * @return
627
	 */
628
	private String getSqlWhere(SortedSet<Integer> regionFks) {
629
		String sqlWhere = "";
630
		for (Integer regionFk : regionFks){
631
			sqlWhere += regionFk + ",";
632
		}
633
		sqlWhere = sqlWhere.substring(0, sqlWhere.length()-1);
634
		return sqlWhere;
635
	}
636

    
637
	/**
638
	 * Returns a map which is filled by the emCode->TdwgCode mapping defined in emArea.
639
	 * Some exceptions are defined for emCode 'Ab','Rf','Uk' and some additional mapping is added
640
	 * for 'Ab / Ab(A)', 'Ga / Ga(F)', 'It / It(I)', 'Ar / Ar(A)','Hs / Hs(S)'
641
	 * @param source
642
	 * @throws SQLException
643
	 */
644
	private Map<String, String> getEmTdwgMap(Source source) throws SQLException {
645
		String sql;
646
		ResultSet rs;
647
		Map<String, String> emTdwgMap = new HashMap<>();
648
		sql = " SELECT EmCode, TDWGCode FROM emArea ";
649
		rs = source.getResultSet(sql);
650
		while (rs.next()){
651
			String emCode = rs.getString("EMCode");
652
			String TDWGCode = rs.getString("TDWGCode");
653
			if (isNotBlank(emCode) ){
654
				emCode = emCode.trim();
655
				if (emCode.equalsIgnoreCase("Ab") || emCode.equalsIgnoreCase("Rf")||
656
						emCode.equalsIgnoreCase("Uk") || emCode.equalsIgnoreCase("Gg")
657
						|| emCode.equalsIgnoreCase("SM") || emCode.equalsIgnoreCase("Tu")){
658
					emTdwgMap.put(emCode, emCode);
659
				}else if (isNotBlank(TDWGCode)){
660
					emTdwgMap.put(emCode, TDWGCode.trim());
661
				}
662
			}
663
		}
664
		emTdwgMap.put("Ab / Ab(A)", "Ab");
665
		emTdwgMap.put("Ga / Ga(F)", "FRA-FR");
666
		emTdwgMap.put("It / It(I)", "ITA");
667
		emTdwgMap.put("Uk / Uk(U)", "Uk");
668
		emTdwgMap.put("Ar / Ar(A)", "TCS-AR");
669
		emTdwgMap.put("Hs / Hs(S)", "SPA-SP");
670
		emTdwgMap.put("Hb / Hb(E)", "IRE-IR");
671

    
672
		return emTdwgMap;
673
	}
674

    
675

    
676
	/**
677
	 * Returns the first non-image gallery description. Creates a new one if no description exists.
678
	 * @param taxon
679
	 * @return
680
	 */
681
	private TaxonDescription getDescription(Taxon taxon) {
682
		TaxonDescription result = null;
683
		for (TaxonDescription taxonDescription : taxon.getDescriptions()){
684
			if (! taxonDescription.isImageGallery()){
685
				result = taxonDescription;
686
			}
687
		}
688
		if (result == null){
689
			result = TaxonDescription.NewInstance(taxon);
690
		}
691
		return result;
692
	}
693

    
694
	@Override
695
	public Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForPartition(ResultSet rs, BerlinModelImportState state) {
696
		String nameSpace;
697
		Class<?> cdmClass;
698
		Set<String> idSet;
699
		Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<>();
700

    
701
		String pos = "0";
702
		try{
703
			Set<String> taxonIdSet = new HashSet<>();
704
			Set<String> nameIdSet = new HashSet<>();
705
			Set<String> referenceIdSet = new HashSet<>();
706
			while (rs.next()){
707
				handleForeignKey(rs, taxonIdSet, "taxonId");
708
				handleForeignKey(rs, taxonIdSet, "factTaxonId");
709
                handleForeignKey(rs, taxonIdSet, "misappliedTaxonId");
710
				handleForeignKey(rs, referenceIdSet, "refId");
711
				handleForeignKey(rs, referenceIdSet, "languageRefRefFk");
712
				handleForeignKey(rs, nameIdSet, "NameInSourceFk");
713
				handleForeignKey(rs, nameIdSet, "PTNameFk");
714
				handleForeignKey(rs, referenceIdSet, "MisNameRefFk");
715
			}
716

    
717
			//name map
718
			nameSpace = BerlinModelTaxonNameImport.NAMESPACE;
719
			cdmClass = TaxonName.class;
720
			idSet = nameIdSet;
721
			@SuppressWarnings("unchecked")
722
            Map<String, TaxonName> nameMap = (Map<String, TaxonName>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
723
			result.put(nameSpace, nameMap);
724

    
725
			//taxon map
726
			nameSpace = BerlinModelTaxonImport.NAMESPACE;
727
			cdmClass = TaxonBase.class;
728
			idSet = taxonIdSet;
729
			@SuppressWarnings("unchecked")
730
            Map<String, TaxonBase<?>> taxonMap = (Map<String, TaxonBase<?>>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
731
			result.put(nameSpace, taxonMap);
732

    
733
			//reference map
734
			nameSpace = BerlinModelReferenceImport.REFERENCE_NAMESPACE;
735
			cdmClass = Reference.class;
736
			idSet = referenceIdSet;
737
			@SuppressWarnings("unchecked")
738
            Map<String, Reference> referenceMap = (Map<String, Reference>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
739
			result.put(nameSpace, referenceMap);
740
			// TODO remove if problem with duplicate DescElement_Annot id is solved
741
		} catch (SQLException e) {
742
			throw new RuntimeException("pos: " +pos, e);
743
		} catch (NullPointerException nep){
744
			logger.error("NullPointerException in getRelatedObjectsForPartition()");
745
		}
746
		return result;
747
	}
748

    
749

    
750
	@Override
751
	protected boolean doCheck(BerlinModelImportState state){
752
		IOValidator<BerlinModelImportState> validator = new BerlinModelCommonNamesImportValidator();
753
		return validator.validate(state);
754
	}
755

    
756

    
757
	@Override
758
	protected boolean isIgnore(BerlinModelImportState state){
759
		return ! state.getConfig().isDoCommonNames();
760
	}
761

    
762
}
(3-3/21)