Project

General

Profile

Download (32.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
import org.springframework.transaction.TransactionStatus;
28

    
29
import eu.etaxonomy.cdm.common.CdmUtils;
30
import eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer;
31
import eu.etaxonomy.cdm.io.berlinModel.in.validation.BerlinModelCommonNamesImportValidator;
32
import eu.etaxonomy.cdm.io.common.IOValidator;
33
import eu.etaxonomy.cdm.io.common.ResultSetPartitioner;
34
import eu.etaxonomy.cdm.io.common.Source;
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.IdentifiableSource;
39
import eu.etaxonomy.cdm.model.common.Language;
40
import eu.etaxonomy.cdm.model.common.Marker;
41
import eu.etaxonomy.cdm.model.common.MarkerType;
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.NamedArea;
46
import eu.etaxonomy.cdm.model.name.TaxonName;
47
import eu.etaxonomy.cdm.model.reference.Reference;
48
import eu.etaxonomy.cdm.model.taxon.Taxon;
49
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
50
import eu.etaxonomy.cdm.model.term.OrderedTermVocabulary;
51
import eu.etaxonomy.cdm.model.term.Representation;
52
import eu.etaxonomy.cdm.model.term.TermVocabulary;
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> regionFkToAreaMap = 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
			TransactionStatus tx = startTransaction();
146
		    SortedSet<Integer> regionFks = new TreeSet<>();
147
			Source source = state.getConfig().getSource();
148

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

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

    
160
			commitTransaction(tx);
161

    
162
			return;
163
		} catch (NumberFormatException e) {
164
			e.printStackTrace();
165
			state.setUnsuccessfull();
166
			return;
167
		} catch (SQLException e) {
168
			e.printStackTrace();
169
			state.setUnsuccessfull();
170
			return;
171
		}
172
	}
173

    
174

    
175
    @Override
176
	public boolean doPartition(@SuppressWarnings("rawtypes") ResultSetPartitioner partitioner, BerlinModelImportState state)  {
177
		boolean success = true ;
178

    
179
		@SuppressWarnings("rawtypes")
180
        Set<TaxonBase> taxaToSave = new HashSet<>();
181
		@SuppressWarnings("unchecked")
182
        Map<String, Taxon> taxonMap = partitioner.getObjectMap(BerlinModelTaxonImport.NAMESPACE);
183
		@SuppressWarnings("unchecked")
184
        Map<String, TaxonName> taxonNameMap = partitioner.getObjectMap(BerlinModelTaxonNameImport.NAMESPACE);
185
		@SuppressWarnings("unchecked")
186
        Map<String, Reference> refMap = partitioner.getObjectMap(BerlinModelReferenceImport.REFERENCE_NAMESPACE);
187

    
188
		Map<String, Language> iso6392Map = new HashMap<>();
189

    
190
	//	logger.warn("MisappliedNameRefFk  not yet implemented for Common Names");
191

    
192
		ResultSet rs = partitioner.getResultSet();
193
		Integer lastCommonNameId = null;
194
		try{
195
			while (rs.next()){
196

    
197
				//create TaxonName element
198
				Integer commonNameId = rs.getInt("CommonNameId");
199
				int taxonId = rs.getInt("taxonId");
200
				Integer factTaxonId = nullSafeInt(rs, "factTaxonId");
201
				Integer accTaxonId = nullSafeInt(rs, "accTaxonId");  //if common name is related to synonym this is the accepted taxon id
202

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

    
218
				if (commonNameId == lastCommonNameId){
219
				    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. ");
220
				}else{
221
				    lastCommonNameId = commonNameId;
222
				}
223

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

    
233
				//commonNameString
234
				if (isBlank(commonNameString)){
235
					String message = "CommonName is empty or null. Do not import record for taxon " + taxonId;
236
					logger.warn(message);
237
					continue;
238
				}
239

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

    
264
				//Language
265
				Language language = getAndHandleLanguage(iso6392Map, iso639_2, iso639_1, languageString, originalLanguageString, state);
266

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

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

    
302
				Reference reference = refMap.get(String.valueOf(languageRefRefFk));
303
				if (reference == null && languageRefRefFk != null){
304
					logger.warn("CommonName reference was null but reference exists. languageRefRefFk = " + languageRefRefFk + "; commonNameId = " + commonNameId);
305
				}
306
				String microCitation = null;
307
				String originalNameString = null;
308

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

    
320
				//MisNameRef
321
				if (misNameRefFk != null){
322
					//Taxon misappliedName = getMisappliedName(biblioRefMap, nomRefMap, misNameRefFk, taxon);
323
					Taxon misappliedNameTaxon = null;
324
					if (misappliedTaxonId != null){
325
						TaxonBase<?> misTaxonBase =  taxonMap.get(String.valueOf(misappliedTaxonId));
326
						if (misTaxonBase == null){
327
							logger.warn("MisappliedName not found for misappliedTaxonId " + misappliedTaxonId + "; commonNameId: " + commonNameId);
328
						}else if (misTaxonBase.isInstanceOf(Taxon.class)){
329
							misappliedNameTaxon = CdmBase.deproxy(misTaxonBase, Taxon.class);
330
						}else{
331
							logger.warn("Misapplied name taxon is not of type Taxon but " + misTaxonBase.getClass().getSimpleName());
332
						}
333
					}else{
334
						Reference sec = refMap.get(String.valueOf(misNameRefFk));
335
						if (nameUsedInSource == null || sec == null){
336
							logger.warn("Taxon name or misapplied name reference is null for common name " + commonNameId);
337
						}else{
338
							misappliedNameTaxon = Taxon.NewInstance(nameUsedInSource, sec);
339
							MarkerType misCommonNameMarker = getMarkerType(state, BerlinModelTransformer.uuidMisappliedCommonName,"Misapplied Common Name in Berlin Model",
340
							        "Misapplied taxon was automatically created by Berlin Model import for a common name with a misapplied name reference", "MCN", getEuroMedMarkerTypeVoc());
341
							Marker marker = Marker.NewInstance(misCommonNameMarker, true);
342
							misappliedNameTaxon.addMarker(marker);
343
							taxaToSave.add(misappliedNameTaxon);
344
							logger.warn("Misapplied name taxon could not be found in database but misapplied name reference exists for common name. " +
345
									"New misapplied name for misapplied reference common name was added. CommonNameId: " + commonNameId);
346
						}
347
					}
348
					if (misappliedNameTaxon != null){
349

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

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

    
368
				}
369

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

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

    
385
				//status
386
				if (isNotBlank(status)){
387
				    TermVocabulary<MarkerType> markerTypeVoc = getEuroMedMarkerTypeVoc();
388
				    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')",
389
				            "recommended", markerTypeVoc);
390
					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')",
391
					        "synonym", markerTypeVoc);
392
                    for (CommonTaxonName commonTaxonName : commonTaxonNames){
393
                        Marker marker = null;
394
                        if (status.equals("recommended")){
395
						    marker = Marker.NewInstance(recommendedMarkerType, true);
396
                        }else if (status.equals("synonym")){
397
                            marker = Marker.NewInstance(synonymMarkerType, true);
398
                        }else if (status.equals("unassessed")){
399
                            //do nothing
400
                        }else{
401
						    logger.warn("Unknown common name status: " + status);
402
						}
403
                        if (marker != null){
404
                            commonTaxonName.addMarker(marker);
405
                        }
406
					}
407
				}
408

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

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

    
426
		//	logger.info( i + " names handled");
427
		getTaxonService().save(taxaToSave);
428
		return success;
429

    
430
	}
431

    
432

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

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

    
476

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

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

    
509
	}
510

    
511

    
512

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

    
531
		ResultSet rs = source.getResultSet(sql);
532
		while (rs.next()){
533
			String strRegionFks = rs.getString("RegionFks");
534
			if (isBlank(strRegionFks)){
535
				continue;
536
			}
537

    
538
			String[] regionFkArray = strRegionFks.split(",");
539
			for (String regionFk: regionFkArray){
540
				regionFk = regionFk.trim();
541
				if (! StringUtils.isNumeric(regionFk) || "".equals(regionFk)  ){
542
					state.setUnsuccessfull();
543
					logger.warn("RegionFk is not numeric: " + regionFk +  " ( part of " + strRegionFks + ")");
544
				}else{
545
					regionFks.add(Integer.valueOf(regionFk));
546
				}
547
			}
548
		}
549
		return;
550
	}
551

    
552

    
553

    
554
	/**
555
	 * Fills the {@link #regionMap} by all emLanguageRegion regions defined in the sql filter.
556
	 * {@link #regionMap} maps emLanguageRegion.RegionId to named areas.
557
	 * @param state
558
	 * @param sqlWhere
559
	 * @param emTdwgMap
560
	 * @throws SQLException
561
	 */
562
	private void fillRegionMap(BerlinModelImportState state, String sqlWhere,
563
			Map<String, NamedArea> emCodeToAreaMap) throws SQLException {
564

    
565
	    Source source = state.getConfig().getSource();
566
		String sql =
567
		      " SELECT RegionId, Region "
568
		    + " FROM  emLanguageRegion "
569
		    + " WHERE RegionId IN ("+ sqlWhere+ ") ";
570
		ResultSet rs = source.getResultSet(sql);
571
		while (rs.next()){
572
			Object regionId = rs.getObject("RegionId");
573
			String region = rs.getString("Region");
574
			String[] splitRegion = region.split("-");
575
			if (splitRegion.length <= 1){
576
				NamedArea newArea = getNamedArea(state, null, region, "Language region '" + region + "'", null, null, null);
577
//				getTermService().save(newArea);
578
				regionFkToAreaMap.put(String.valueOf(regionId), newArea);
579
				logger.warn("Found new area: " +  region);
580
			}else if (splitRegion.length == 2){
581
				String emCode = splitRegion[1].trim().replace(" ", "");
582

    
583
				NamedArea area = emCodeToAreaMap.get(emCode);
584
				if (area == null){
585
				    String[] splits = emCode.split("/");
586
				    if (splits.length == 2){
587
				        area = emCodeToAreaMap.get(splits[0]);
588
		            }
589
				    if (area != null){
590
				        logger.warn("emCode ambigous. Use larger area: " +  CdmUtils.Nz(emCode) + "->" + regionId);
591
				    }else{
592
				        logger.warn("emCode not recognized. Region not defined: " +  CdmUtils.Nz(emCode) + "->" + regionId);
593
				    }
594
				}
595
				if (area != null){
596
				    regionFkToAreaMap.put(String.valueOf(regionId), area);
597
				}
598
			}
599
		}
600
	}
601

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

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

    
653

    
654

    
655
    /**
656
     * @param source
657
     * @return
658
     * @throws SQLException
659
     */
660
    private Map<String, NamedArea> getEmCodeToAreaMap(Source source) throws SQLException {
661
        Map<String, NamedArea> emCodeToAreaMap = new HashMap<>();
662
        String sql =
663
              " SELECT EmCode, AreaId "
664
            + " FROM emArea ";
665
        ResultSet rs = source.getResultSet(sql);
666
        while (rs.next()){
667

    
668
            String emCode = rs.getString("EMCode");
669
            if (isNotBlank(emCode)){
670
                Integer areaId = rs.getInt("AreaId");
671
                NamedArea area = getAreaByAreaId(areaId);
672
                if (area != null){
673
                    emCodeToAreaMap.put(emCode.trim(), area);
674
                }else{
675
                    logger.warn("Area not found for areaId " + areaId);
676
                }
677
            }
678

    
679
        }
680

    
681
//        emTdwgMap.put("Ab / Ab(A)", "Ab");
682

    
683
        return emCodeToAreaMap;
684
    }
685

    
686
    /**
687
     * @param emCode
688
     * @return
689
     */
690
    private NamedArea getAreaByAreaId(int areaId) {
691
        NamedArea result = null;
692
        String areaIdStr = String.valueOf(areaId);
693
        OrderedTermVocabulary<NamedArea> voc = getAreaVoc();
694
        getVocabularyService().update(voc);
695
        for (NamedArea area : voc.getTerms()){
696
            for (IdentifiableSource source : area.getSources()){
697
                if (areaIdStr.equals(source.getIdInSource()) && BerlinModelAreaImport.NAMESPACE.equals(source.getIdNamespace())){
698
                    if (result != null){
699
                        logger.warn("Result for areaId already exists. areaId: " + areaId);
700
                    }
701
                    result = area;
702
                }
703
            }
704
        }
705
        return result;
706
    }
707

    
708
    private OrderedTermVocabulary<NamedArea> areaVoc;
709
    @SuppressWarnings("unchecked")
710
    private OrderedTermVocabulary<NamedArea> getAreaVoc(){
711
        if (areaVoc == null){
712
            areaVoc = (OrderedTermVocabulary<NamedArea>)getVocabularyService().find(BerlinModelTransformer.uuidVocEuroMedAreas);
713
        }
714
        return areaVoc;
715
    }
716

    
717

    
718
	/**
719
	 * Returns the first non-image gallery description. Creates a new one if no description exists.
720
	 * @param taxon
721
	 * @return
722
	 */
723
	private TaxonDescription getDescription(Taxon taxon) {
724
		TaxonDescription result = null;
725
		for (TaxonDescription taxonDescription : taxon.getDescriptions()){
726
			if (! taxonDescription.isImageGallery()){
727
				result = taxonDescription;
728
			}
729
		}
730
		if (result == null){
731
			result = TaxonDescription.NewInstance(taxon);
732
		}
733
		return result;
734
	}
735

    
736
	@Override
737
	public Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForPartition(ResultSet rs, BerlinModelImportState state) {
738
		String nameSpace;
739
		Class<?> cdmClass;
740
		Set<String> idSet;
741
		Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<>();
742

    
743
		String pos = "0";
744
		try{
745
			Set<String> taxonIdSet = new HashSet<>();
746
			Set<String> nameIdSet = new HashSet<>();
747
			Set<String> referenceIdSet = new HashSet<>();
748
			while (rs.next()){
749
				handleForeignKey(rs, taxonIdSet, "taxonId");
750
				handleForeignKey(rs, taxonIdSet, "factTaxonId");
751
                handleForeignKey(rs, taxonIdSet, "misappliedTaxonId");
752
				handleForeignKey(rs, referenceIdSet, "refId");
753
				handleForeignKey(rs, referenceIdSet, "languageRefRefFk");
754
				handleForeignKey(rs, nameIdSet, "NameInSourceFk");
755
				handleForeignKey(rs, nameIdSet, "PTNameFk");
756
				handleForeignKey(rs, referenceIdSet, "MisNameRefFk");
757
			}
758

    
759
			//name map
760
			nameSpace = BerlinModelTaxonNameImport.NAMESPACE;
761
			cdmClass = TaxonName.class;
762
			idSet = nameIdSet;
763
			@SuppressWarnings("unchecked")
764
            Map<String, TaxonName> nameMap = (Map<String, TaxonName>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
765
			result.put(nameSpace, nameMap);
766

    
767
			//taxon map
768
			nameSpace = BerlinModelTaxonImport.NAMESPACE;
769
			cdmClass = TaxonBase.class;
770
			idSet = taxonIdSet;
771
			@SuppressWarnings("unchecked")
772
            Map<String, TaxonBase<?>> taxonMap = (Map<String, TaxonBase<?>>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
773
			result.put(nameSpace, taxonMap);
774

    
775
			//reference map
776
			nameSpace = BerlinModelReferenceImport.REFERENCE_NAMESPACE;
777
			cdmClass = Reference.class;
778
			idSet = referenceIdSet;
779
			@SuppressWarnings("unchecked")
780
            Map<String, Reference> referenceMap = (Map<String, Reference>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
781
			result.put(nameSpace, referenceMap);
782
			// TODO remove if problem with duplicate DescElement_Annot id is solved
783
		} catch (SQLException e) {
784
			throw new RuntimeException("pos: " + pos, e);
785
		} catch (NullPointerException nep){
786
			logger.error("NullPointerException in getRelatedObjectsForPartition()");
787
		}
788
		return result;
789
	}
790

    
791

    
792
	@Override
793
	protected boolean doCheck(BerlinModelImportState state){
794
		IOValidator<BerlinModelImportState> validator = new BerlinModelCommonNamesImportValidator();
795
		return validator.validate(state);
796
	}
797

    
798

    
799
	@Override
800
	protected boolean isIgnore(BerlinModelImportState state){
801
		return ! state.getConfig().isDoCommonNames();
802
	}
803

    
804
}
(4-4/22)