Project

General

Profile

Download (33.9 KB) Statistics
| Branch: | Revision:
1
/**
2
* Copyright (C) 2007 EDIT
3
* European Distributed Institute of Taxonomy 
4
* http://www.e-taxonomy.eu
5
* 
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9

    
10
package eu.etaxonomy.cdm.io.berlinModel.in;
11

    
12
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.REF_ARTICLE;
13
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.REF_BOOK;
14
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.REF_CONFERENCE_PROCEEDINGS;
15
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.REF_DATABASE;
16
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.REF_INFORMAL;
17
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.REF_JOURNAL;
18
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.REF_JOURNAL_VOLUME;
19
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.REF_PART_OF_OTHER_TITLE;
20
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.REF_PRINT_SERIES;
21
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.REF_UNKNOWN;
22
import static eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer.REF_WEBSITE;
23
import static eu.etaxonomy.cdm.io.common.ImportHelper.NO_OVERWRITE;
24
import static eu.etaxonomy.cdm.io.common.ImportHelper.OBLIGATORY;
25
import static eu.etaxonomy.cdm.io.common.ImportHelper.OVERWRITE;
26

    
27
import java.net.URI;
28
import java.net.URISyntaxException;
29
import java.sql.ResultSet;
30
import java.sql.SQLException;
31
import java.util.ArrayList;
32
import java.util.Arrays;
33
import java.util.HashMap;
34
import java.util.HashSet;
35
import java.util.List;
36
import java.util.Map;
37
import java.util.Set;
38
import java.util.UUID;
39

    
40
import org.apache.commons.lang.StringUtils;
41
import org.apache.log4j.Logger;
42
import org.springframework.stereotype.Component;
43

    
44
import eu.etaxonomy.cdm.common.CdmUtils;
45
import eu.etaxonomy.cdm.io.berlinModel.in.validation.BerlinModelReferenceImportValidator;
46
import eu.etaxonomy.cdm.io.common.ICdmIO;
47
import eu.etaxonomy.cdm.io.common.IImportConfigurator;
48
import eu.etaxonomy.cdm.io.common.ImportHelper;
49
import eu.etaxonomy.cdm.io.common.ResultSetPartitioner;
50
import eu.etaxonomy.cdm.io.common.Source;
51
import eu.etaxonomy.cdm.io.common.mapping.CdmAttributeMapperBase;
52
import eu.etaxonomy.cdm.io.common.mapping.CdmIoMapping;
53
import eu.etaxonomy.cdm.io.common.mapping.CdmSingleAttributeMapperBase;
54
import eu.etaxonomy.cdm.io.common.mapping.DbImportExtensionMapper;
55
import eu.etaxonomy.cdm.io.common.mapping.DbImportMarkerMapper;
56
import eu.etaxonomy.cdm.io.common.mapping.DbSingleAttributeImportMapperBase;
57
import eu.etaxonomy.cdm.io.common.mapping.berlinModel.CdmOneToManyMapper;
58
import eu.etaxonomy.cdm.io.common.mapping.berlinModel.CdmStringMapper;
59
import eu.etaxonomy.cdm.io.common.mapping.berlinModel.CdmUriMapper;
60
import eu.etaxonomy.cdm.model.agent.Team;
61
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
62
import eu.etaxonomy.cdm.model.common.CdmBase;
63
import eu.etaxonomy.cdm.model.common.ExtensionType;
64
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
65
import eu.etaxonomy.cdm.model.common.Marker;
66
import eu.etaxonomy.cdm.model.common.MarkerType;
67
import eu.etaxonomy.cdm.model.reference.IArticle;
68
import eu.etaxonomy.cdm.model.reference.IBookSection;
69
import eu.etaxonomy.cdm.model.reference.IPrintSeries;
70
import eu.etaxonomy.cdm.model.reference.Reference;
71
import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
72

    
73
/**
74
 * @author a.mueller
75
 * @created 20.03.2008
76
 */
77
@Component
78
public class BerlinModelReferenceImport extends BerlinModelImportBase {
79
	private static final Logger logger = Logger.getLogger(BerlinModelReferenceImport.class);
80

    
81
	public static final String REFERENCE_NAMESPACE = "Reference";
82
	
83
	public static final UUID REF_DEPOSITED_AT_UUID = UUID.fromString("23ca88c7-ce73-41b2-8ca3-2cb22f013beb");
84
	public static final UUID REF_SOURCE_UUID = UUID.fromString("d6432582-2216-4b08-b0db-76f6c1013141");
85
	public static final UUID DATE_STRING_UUID = UUID.fromString("e4130eae-606e-4b0c-be4f-e93dc161be7d");
86
	public static final UUID IS_PAPER_UUID = UUID.fromString("8a326129-d0d0-4f9d-bbdf-8d86b037c65e");
87
	
88
	
89
	private int modCount = 1000;
90
	private static final String pluralString = "references";
91
	private static final String dbTableName = "reference";
92

    
93
	
94
	public BerlinModelReferenceImport(){
95
		super(dbTableName, pluralString);
96
	}
97
	
98
	protected void initializeMappers(BerlinModelImportState state){
99
		for (CdmAttributeMapperBase mapper: classMappers){
100
			if (mapper instanceof DbSingleAttributeImportMapperBase){
101
				DbSingleAttributeImportMapperBase singleMapper = (DbSingleAttributeImportMapperBase)mapper;
102
				singleMapper.initialize(state, Reference.class);
103
			}
104
		}
105
		return;
106
	}
107
	
108
	protected static CdmAttributeMapperBase[] classMappers = new CdmAttributeMapperBase[]{
109
		new CdmStringMapper("edition", "edition"),
110
		new CdmStringMapper("volume", "volume"),
111
		new CdmStringMapper("publisher", "publisher"),
112
		new CdmStringMapper("publicationTown", "placePublished"),
113
		new CdmStringMapper("isbn", "isbn"),
114
		new CdmStringMapper("isbn", "isbn"),
115
		new CdmStringMapper("pageString", "pages"),
116
		new CdmStringMapper("series", "series"),
117
		new CdmStringMapper("issn", "issn"),
118
		new CdmUriMapper("url", "uri"),
119
		DbImportExtensionMapper.NewInstance("NomStandard", ExtensionType.NOMENCLATURAL_STANDARD()),
120
		DbImportExtensionMapper.NewInstance("DateString", DATE_STRING_UUID, "Date String", "Date String", "dates"),
121
		DbImportExtensionMapper.NewInstance("RefDepositedAt", REF_DEPOSITED_AT_UUID, "RefDepositedAt", "reference is deposited at", "at"),
122
		DbImportExtensionMapper.NewInstance("RefSource", REF_SOURCE_UUID, "RefSource", "reference source", "source"),
123
		DbImportMarkerMapper.NewInstance("isPaper", IS_PAPER_UUID, "is paper", "is paper", "paper", false)
124
	};
125

    
126
	
127
	protected static String[] operationalAttributes = new String[]{
128
		"refId", "refCache", "nomRefCache", "preliminaryFlag", "inRefFk", "title", "nomTitleAbbrev",
129
		"refAuthorString", "nomAuthorTeamFk",
130
		"refCategoryFk", "thesisFlag", "informalRefCategory", "idInSource"
131
	};
132
	
133
	protected static String[] createdAndNotesAttributes = new String[]{
134
			"created_When", "updated_When", "created_Who", "updated_Who", "notes"
135
	};
136
	
137
	protected static String[] unclearMappers = new String[]{
138
			/*"isPaper",*/ "exportDate", 
139
	};
140
	
141
	//TODO isPaper
142
	//
143
	
144
	
145
	
146
	//type to count the references nomReferences that have been created and saved
147
	private class RefCounter{
148
		RefCounter() {refCount = 0;};
149
		int refCount;
150

    
151
		public String toString(){return String.valueOf(refCount) ;};
152
	}
153

    
154

    
155
	/* (non-Javadoc)
156
	 * @see eu.etaxonomy.cdm.io.berlinModel.in.BerlinModelImportBase#getRecordQuery(eu.etaxonomy.cdm.io.berlinModel.in.BerlinModelImportConfigurator)
157
	 */
158
	@Override
159
	protected String getRecordQuery(BerlinModelImportConfigurator config) {
160
		return null;  //not needed
161
	}
162

    
163
	@Override
164
	protected void doInvoke(BerlinModelImportState state){
165
		logger.info("start make " + getPluralString() + " ...");
166

    
167
		boolean success = true;
168
		initializeMappers(state);
169
		BerlinModelImportConfigurator config = state.getConfig();
170
		Source source = config.getSource();
171

    
172
		String strSelectId = " SELECT Reference.RefId as refId ";
173
		String strSelectFull = 
174
			" SELECT Reference.* ,InReference.RefCategoryFk as InRefCategoryFk, RefSource.RefSource " ;
175
		String strFrom =  " FROM %s  " + 
176
		    	" LEFT OUTER JOIN Reference as InReference ON InReference.refId = Reference.inRefFk " +
177
				" LEFT OUTER JOIN RefSource ON Reference.RefSourceFk = RefSource.RefSourceId " +
178
		    	" WHERE (1=1) ";
179
		String strWherePartitioned = " AND (Reference.refId IN ("+ ID_LIST_TOKEN + ") ) "; 
180
		
181
		String referenceTable = CdmUtils.Nz(state.getConfig().getReferenceIdTable());
182
		referenceTable = referenceTable.isEmpty() ? " Reference"  : referenceTable + " as Reference ";
183
		String strIdFrom = String.format(strFrom, referenceTable );
184
		
185
		String strSelectIdBase = strSelectId + strIdFrom;
186
		
187
		String referenceFilter = CdmUtils.Nz(state.getConfig().getReferenceIdTable());
188
		if (! referenceFilter.isEmpty()){
189
			referenceFilter = " AND " + referenceFilter + " ";
190
		}
191
		referenceFilter = "";  //don't use it for now
192
		
193
		String strIdQueryFirstPath = strSelectId + strIdFrom ;
194
		String strIdQuerySecondPath = strSelectId + strIdFrom + " AND (Reference.InRefFk is NOT NULL) ";
195
		
196
//		if (config.getDoReferences() == CONCEPT_REFERENCES){
197
//			strIdQueryNoInRef += " AND ( Reference.refId IN ( SELECT ptRefFk FROM PTaxon) ) " + referenceFilter;
198
//		}
199

    
200
		String strRecordQuery = strSelectFull + String.format(strFrom, " Reference ") + strWherePartitioned;
201
		
202
		int recordsPerTransaction = config.getRecordsPerTransaction();
203
		try{
204
			//firstPath 
205
			ResultSetPartitioner partitioner = ResultSetPartitioner.NewInstance(source, strIdQueryFirstPath, strRecordQuery, recordsPerTransaction);
206
			while (partitioner.nextPartition()){
207
				partitioner.doPartition(this, state);
208
			}
209
			logger.info("end make references without in-references ... " + getSuccessString(success));
210
			state.setReferenceSecondPath(true);
211

    
212
//			if (config.getDoReferences() == ALL || config.getDoReferences() == NOMENCLATURAL){
213

    
214
			//secondPath
215
			partitioner = ResultSetPartitioner.NewInstance(source, strIdQuerySecondPath, strRecordQuery, recordsPerTransaction);
216
			while (partitioner.nextPartition()){
217
				partitioner.doPartition(this, state);
218
			}
219
			logger.info("end make references with no 1 in-reference ... " + getSuccessString(success));
220
			state.setReferenceSecondPath(false);
221
			
222
//			}
223

    
224
		} catch (SQLException e) {
225
			logger.error("SQLException:" +  e);
226
			state.setUnsuccessfull();
227
			return;
228
		}
229
		logger.info("end make " + getPluralString() + " ... " + getSuccessString(success));
230
		if (! success){
231
			state.setUnsuccessfull();
232
		}
233
		return;
234
	}
235

    
236
	
237
	
238

    
239
	/* (non-Javadoc)
240
	 * @see eu.etaxonomy.cdm.io.berlinModel.in.IPartitionedIO#doPartition(eu.etaxonomy.cdm.io.berlinModel.in.ResultSetPartitioner, eu.etaxonomy.cdm.io.berlinModel.in.BerlinModelImportState)
241
	 */
242
	public boolean doPartition(ResultSetPartitioner partitioner, BerlinModelImportState state) {
243
		if (state.isReferenceSecondPath()){
244
			return doPartitionSecondPath(partitioner, state);
245
		}
246
		boolean success = true;
247

    
248
		Map<Integer, Reference> refToSave = new HashMap<Integer, Reference>();
249
		
250
		Map<String, Reference> relatedReferences = partitioner.getObjectMap(REFERENCE_NAMESPACE);
251
		
252
		BerlinModelImportConfigurator config = state.getConfig();
253
		
254
		try {
255

    
256
				int i = 0;
257
				RefCounter refCounter  = new RefCounter();
258
				
259
				ResultSet rs = partitioner.getResultSet();
260

    
261
				//for each resultset
262
				while (rs.next()){
263
					if ((i++ % modCount) == 0 && i!= 1 ){ logger.info("References handled: " + (i-1) + " in round -" );}
264
				
265
					success &= makeSingleReferenceRecord(rs, state, partitioner, refToSave, relatedReferences, refCounter);
266
				} // end resultSet
267
								
268
				//for the concept reference a fixed uuid may be needed -> change uuid
269
				Integer sourceSecId = (Integer)config.getSourceSecId();
270
				Reference<?> sec = refToSave.get(sourceSecId);
271

    
272
				if (sec != null){
273
					sec.setUuid(config.getSecUuid());
274
					logger.info("SecUuid changed to: " + config.getSecUuid());
275
				}
276
				
277
				//save and store in map
278
				logger.info("Save references (" + refCounter.refCount + ")");
279
				getReferenceService().saveOrUpdate(refToSave.values());
280

    
281
//			}//end resultSetList	
282

    
283
//			logger.info("end makeReferences ..." + getSuccessString(success));;
284
			return success;
285
		} catch (SQLException e) {
286
			logger.error("SQLException:" +  e);
287
			return false;
288
		}
289
	}
290

    
291

    
292

    
293
	/**
294
	 * Adds the inReference to the according references.
295
	 * @param partitioner
296
	 * @param state
297
	 * @return
298
	 */
299
	private boolean doPartitionSecondPath(ResultSetPartitioner partitioner, BerlinModelImportState state) {
300
		boolean success = true;
301

    
302
		Map<Integer, Reference> refToSave = new HashMap<Integer, Reference>();
303
		
304
		Map<String, Reference> relatedReferencesMap = partitioner.getObjectMap(REFERENCE_NAMESPACE);
305
		
306
		try {
307
				int i = 0;
308
				RefCounter refCounter  = new RefCounter();
309
			
310
				ResultSet rs = partitioner.getResultSet();
311
				//for each resultset
312
				while (rs.next()){
313
					if ((i++ % modCount) == 0 && i!= 1 ){ logger.info("References handled: " + (i-1) + " in round -" );}
314
				
315
					Integer refId = rs.getInt("refId");
316
					Integer inRefFk = rs.getInt("inRefFk");
317
					
318
					if (inRefFk != null){
319
						
320
						Reference<?> thisRef = relatedReferencesMap.get(String.valueOf(refId));
321
						
322
						Reference<?> inRef = relatedReferencesMap.get(String.valueOf(inRefFk));
323
						
324
						if (thisRef != null){
325
							if (inRef == null){
326
								logger.warn("No InRef found for nomRef: " + thisRef.getTitleCache() + "; RefId: " +  refId + "; inRefFK: " +  inRefFk);
327
							}
328
							thisRef.setInReference(inRef);
329
							refToSave.put(refId, thisRef);
330
							thisRef.setTitleCache(null);
331
							thisRef.getTitleCache();
332
						}
333
					}
334
					
335
				} // end resultSet
336

    
337
				//save and store in map
338
				logger.info("Save references (" + refCounter.refCount + ")");
339
				getReferenceService().saveOrUpdate(refToSave.values());
340
				
341
//			}//end resultSetList	
342

    
343
//			logger.info("end makeReferences ..." + getSuccessString(success));;
344
			return success;
345
		} catch (SQLException e) {
346
			logger.error("SQLException:" +  e);
347
			return false;
348
		}
349
	}
350

    
351

    
352
	
353
	/* (non-Javadoc)
354
	 * @see eu.etaxonomy.cdm.io.berlinModel.in.IPartitionedIO#getRelatedObjectsForPartition(java.sql.ResultSet)
355
	 */
356
	public Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForPartition(ResultSet rs) {
357
		String nameSpace;
358
		Class cdmClass;
359
		Set<String> idSet;
360
		
361
		Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<Object, Map<String, ? extends CdmBase>>();
362
		
363
		try{
364
			Set<String> teamIdSet = new HashSet<String>();
365
			Set<String> referenceIdSet = new HashSet<String>();
366
			
367
			while (rs.next()){
368
				handleForeignKey(rs, teamIdSet, "NomAuthorTeamFk");
369
				handleForeignKey(rs, referenceIdSet, "InRefFk");
370
				//TODO only needed in second path but state not available here to check if state is second path
371
				handleForeignKey(rs, referenceIdSet, "refId");
372
			}
373
			
374
			//team map
375
			nameSpace = BerlinModelAuthorTeamImport.NAMESPACE;
376
			cdmClass = Team.class;
377
			idSet = teamIdSet;
378
			Map<String, Team> teamMap = (Map<String, Team>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
379
			result.put(nameSpace, teamMap);
380

    
381
			//reference map
382
			nameSpace = BerlinModelReferenceImport.REFERENCE_NAMESPACE;
383
			cdmClass = Reference.class;
384
			idSet = referenceIdSet;
385
			Map<String, Reference> referenceMap = (Map<String, Reference>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
386
			result.put(nameSpace, referenceMap);
387
			
388
		} catch (SQLException e) {
389
			throw new RuntimeException(e);
390
		}
391
		return result;
392
	}
393
	
394
	
395
	/**
396
	 * Handles a single reference record
397
	 * @param rs
398
	 * @param state
399
	 * @param biblioRefToSave
400
	 * @param nomRefToSave
401
	 * @param relatedBiblioReferences
402
	 * @param relatedNomReferences
403
	 * @param refCounter
404
	 * @return
405
	 */
406
	private boolean makeSingleReferenceRecord(
407
				ResultSet rs, 
408
				BerlinModelImportState state,
409
				ResultSetPartitioner<BerlinModelImportState> partitioner,
410
				Map<Integer, Reference> refToSave, 
411
				Map<String, Reference> relatedReferences, 
412
				RefCounter refCounter){
413
		boolean success = true;
414

    
415
		Integer refId = null;
416
		try {
417
			Map<String, Object> valueMap = getValueMap(rs);
418
			
419
			Integer categoryFk = (Integer)valueMap.get("refCategoryFk".toLowerCase());
420
			refId = (Integer)valueMap.get("refId".toLowerCase());
421
			Boolean thesisFlag = (Boolean)valueMap.get("thesisFlag".toLowerCase());
422
			
423
			
424
			Reference<?> referenceBase;
425
			logger.debug("RefCategoryFk: " + categoryFk);
426
			
427
			if (thesisFlag){
428
				referenceBase = makeThesis(valueMap);
429
			}else if (categoryFk == REF_JOURNAL){
430
				referenceBase = makeJournal(valueMap);
431
			}else if(categoryFk == REF_BOOK){
432
				referenceBase = makeBook(valueMap, refToSave, relatedReferences);
433
			}else if(categoryFk == REF_DATABASE){
434
				referenceBase = makeDatabase(valueMap);
435
			}else if(categoryFk == REF_INFORMAL){
436
				referenceBase = makeInformal(valueMap);
437
			}else if(categoryFk == REF_WEBSITE){
438
				referenceBase = makeWebSite(valueMap);
439
			}else if(categoryFk == REF_UNKNOWN){
440
				referenceBase = makeUnknown(valueMap);
441
			}else if(categoryFk == REF_PRINT_SERIES){
442
				referenceBase = makePrintSeries(valueMap);
443
			}else if(categoryFk == REF_CONFERENCE_PROCEEDINGS){
444
				referenceBase = makeProceedings(valueMap);
445
			}else if(categoryFk == REF_ARTICLE){
446
				referenceBase = makeArticle(valueMap, refToSave, relatedReferences);
447
			}else if(categoryFk == REF_JOURNAL_VOLUME){
448
				referenceBase = makeJournalVolume(valueMap);
449
			}else if(categoryFk == REF_PART_OF_OTHER_TITLE){
450
				referenceBase = makePartOfOtherTitle(valueMap, refToSave, relatedReferences);
451
			}else{
452
				logger.warn("Unknown categoryFk (" + categoryFk + "). Create 'Generic instead'");
453
				referenceBase = ReferenceFactory.newGeneric();
454
				success = false;
455
			}
456
							
457
			//refYear
458
			String refYear = (String)valueMap.get("refYear".toLowerCase());
459
			referenceBase.setDatePublished(ImportHelper.getDatePublished(refYear)); 
460
			
461
			//created, updated, notes
462
			doCreatedUpdatedNotes(state, referenceBase, rs);						
463
			
464
			//idInSource
465
			String idInSource = (String)valueMap.get("IdInSource".toLowerCase());
466
			if (isNotBlank(idInSource)){
467
				IdentifiableSource source = IdentifiableSource.NewDataImportInstance(idInSource);
468
				source.setIdNamespace("import to Berlin Model");
469
				referenceBase.addSource(source);
470
			}
471
			
472
			//nom&BiblioReference  - must be last because a clone is created
473
			success &= makeNomAndBiblioReference(rs, state, partitioner, refId, referenceBase, refCounter, refToSave);
474

    
475

    
476
		} catch (Exception e) {
477
			logger.warn("Reference with BM refId '" + CdmUtils.Nz(refId) +  "' threw Exception and could not be saved");
478
			e.printStackTrace();
479
			success = false;
480
		}
481
		return success;
482
	}
483

    
484
	
485
	/**
486
	 * Creates and saves a nom. reference and a biblio. reference after checking necessity
487
	 * @param rs
488
	 * @param refId
489
	 * @param ref
490
	 * @param refCounter
491
	 * @param biblioRefToSave
492
	 * @param nomRefToSave
493
	 * @param teamMap
494
	 * @param stores
495
	 * @return
496
	 * @throws SQLException
497
	 */
498
	private boolean makeNomAndBiblioReference(
499
				ResultSet rs, 
500
				BerlinModelImportState state,
501
				ResultSetPartitioner partitioner,
502
				int refId, 
503
				Reference<?> ref,  
504
				RefCounter refCounter, 
505
				Map<Integer, Reference> refToSave
506
				) throws SQLException{
507
		
508
		Map<String, Team> teamMap = partitioner.getObjectMap(BerlinModelAuthorTeamImport.NAMESPACE);
509
		
510
		String refCache = rs.getString("refCache");
511
		String nomRefCache = rs.getString("nomRefCache");
512
		String title = rs.getString("title");
513
		String nomTitleAbbrev = rs.getString("nomTitleAbbrev");
514
		boolean isPreliminary = rs.getBoolean("PreliminaryFlag");
515
		String refAuthorString = rs.getString("refAuthorString");
516
		Integer nomAuthorTeamFk = rs.getInt("NomAuthorTeamFk");
517
		String strNomAuthorTeamFk = String.valueOf(nomAuthorTeamFk);
518
		TeamOrPersonBase<?> nomAuthor = teamMap.get(strNomAuthorTeamFk);
519

    
520
		Reference<?> sourceReference = state.getTransactionalSourceReference();
521
		
522
		//preliminary
523
		if (isPreliminary){
524
			ref.setAbbrevTitleCache(nomRefCache, true);
525
			ref.setTitleCache(refCache, true);
526
		}
527

    
528
		//title/abbrevTitle
529
		if (StringUtils.isNotBlank(nomTitleAbbrev)){
530
			ref.setAbbrevTitle(nomTitleAbbrev);
531
		}
532
		if (StringUtils.isNotBlank(title)){
533
			ref.setTitle(title);
534
		}
535

    
536
		//author
537
		TeamOrPersonBase<?> author = getAuthorTeam(refAuthorString , nomAuthor);
538
		ref.setAuthorTeam(author);
539
		
540
		//save
541
		if (! refToSave.containsKey(refId)){
542
			refToSave.put(refId, ref);
543
		}else{
544
			logger.warn("Duplicate refId in Berlin Model database. Second reference was not imported !!");
545
		}
546
		refCounter.refCount++;
547
		
548
		//refId
549
		ImportHelper.setOriginalSource(ref, sourceReference, refId, REFERENCE_NAMESPACE);
550
		
551
		return true;
552
	}
553
	
554
	/**
555
	 * Copies the created and updated information from the nomReference to the cloned bibliographic reference
556
	 * @param referenceBase
557
	 * @param nomReference
558
	 */
559
	private void copyCreatedUpdated(Reference<?> biblioReference, Reference nomReference) {
560
		biblioReference.setCreatedBy(nomReference.getCreatedBy());
561
		biblioReference.setCreated(nomReference.getCreated());
562
		biblioReference.setUpdatedBy(nomReference.getUpdatedBy());
563
		biblioReference.setUpdated(nomReference.getUpdated());
564
		
565
	}
566

    
567
	private Reference<?> makeArticle (Map<String, Object> valueMap, Map<Integer, Reference> refToSave, Map<String, Reference> relatedReferences){
568
		
569
		IArticle article = ReferenceFactory.newArticle();
570
		Object inRefFk = valueMap.get("inRefFk".toLowerCase());
571
		Integer inRefCategoryFk = (Integer)valueMap.get("inRefCategoryFk".toLowerCase());
572
		Integer refId = (Integer)valueMap.get("refId".toLowerCase());
573
		
574
		if (inRefFk != null){
575
			if (inRefCategoryFk != REF_JOURNAL){
576
				logger.warn("Wrong inrefCategory for Article (refID = " + refId +"). Type must be 'Journal' but was not (RefCategoryFk=" + inRefCategoryFk + "))." +
577
					" InReference was added anyway! ");
578
			}
579
		}else{
580
			logger.warn ("Article has no inreference: " + refId);
581
		}
582
		makeStandardMapper(valueMap, (Reference)article); //url, pages, series, volume
583
		return (Reference)article;
584
	}
585
	
586
	private Reference<?> makePartOfOtherTitle (Map<String, Object> valueMap, 
587
			Map<Integer, Reference> refToSave, 
588
			Map<String, Reference> relatedReferences){
589
		
590
		Reference<?> result;
591
		Object inRefFk = valueMap.get("inRefFk".toLowerCase());
592
		Integer inRefCategoryFk = (Integer)valueMap.get("inRefCategoryFk".toLowerCase());
593
		Integer refId = (Integer)valueMap.get("refId".toLowerCase());
594
		
595
		if (inRefCategoryFk == null){
596
			//null -> error
597
			logger.warn("Part-Of-Other-Title has no inRefCategoryFk! RefId = " + refId + ". ReferenceType set to Generic.");
598
			result = makeUnknown(valueMap);
599
		}else if (inRefFk == null){
600
			logger.warn("Part-Of-Other-Title has in in reference: " + refId);
601
			result = makeUnknown(valueMap);
602
		}else if (inRefCategoryFk == REF_BOOK){
603
			//BookSection
604
			IBookSection bookSection = ReferenceFactory.newBookSection();
605
			result = (Reference<?>)bookSection;
606
		}else if (inRefCategoryFk == REF_ARTICLE){
607
			//Article
608
			//TODO 
609
			logger.info("Reference (refId = " + refId + ") of type 'part_of_other_title' is part of 'article'." +
610
					" There is no specific reference type for such in references yet. Generic reference created instead") ;
611
			result = ReferenceFactory.newGeneric();
612
		}else if (inRefCategoryFk == REF_JOURNAL){
613
			//TODO 
614
			logger.warn("Reference (refId = " + refId + ") of type 'part_of_other_title' has inReference of type 'journal'." +
615
					" This is not allowed! Generic reference created instead") ;
616
			result = ReferenceFactory.newGeneric();
617
			result.addMarker(Marker.NewInstance(MarkerType.TO_BE_CHECKED(), true));
618
		}else{
619
			logger.warn("InReference type (catFk = " + inRefCategoryFk + ") of part-of-reference not recognized for refId " + refId + "." +
620
				" Create 'Generic' reference instead");
621
			result = ReferenceFactory.newGeneric();
622
		}
623
		makeStandardMapper(valueMap, result); //url, pages
624
		return result;
625
	}
626
	
627

    
628
	/**
629
	 * @param inRefFkInt
630
	 * @param biblioRefToSave
631
	 * @param nomRefToSave
632
	 * @param relatedBiblioReferences
633
	 * @param relatedNomReferences
634
	 * @return
635
	 */
636
	private boolean existsInMapOrToSave(Integer inRefFkInt, Map<Integer, Reference> refToSave, Map<String, Reference> relatedReferences) {
637
		boolean result = false;
638
		if (inRefFkInt == null){
639
			return false;
640
		}
641
		result |= refToSave.containsKey(inRefFkInt);
642
		result |= relatedReferences.containsKey(String.valueOf(inRefFkInt));
643
		return result;
644
	}
645

    
646
	private Reference<?> makeWebSite(Map<String, Object> valueMap){
647
		if (logger.isDebugEnabled()){logger.debug("RefType 'Website'");}
648
		Reference<?> webPage = ReferenceFactory.newWebPage();
649
		makeStandardMapper(valueMap, webPage); //placePublished, publisher
650
		return webPage;
651
	}
652
	
653
	private Reference<?> makeUnknown(Map<String, Object> valueMap){
654
		if (logger.isDebugEnabled()){logger.debug("RefType 'Unknown'");}
655
		Reference<?> generic = ReferenceFactory.newGeneric();
656
//		generic.setSeries(series);
657
		makeStandardMapper(valueMap, generic); //pages, placePublished, publisher, series, volume
658
		return generic;
659
	}
660

    
661
	private Reference<?> makeInformal(Map<String, Object> valueMap){
662
		if (logger.isDebugEnabled()){logger.debug("RefType 'Informal'");}
663
		Reference<?> generic = ReferenceFactory.newGeneric();
664
//		informal.setSeries(series);
665
		makeStandardMapper(valueMap, generic);//editor, pages, placePublished, publisher, series, volume
666
		String informal = (String)valueMap.get("InformalRefCategory".toLowerCase());
667
		if (CdmUtils.isNotEmpty(informal) ){
668
			generic.addExtension(informal, ExtensionType.INFORMAL_CATEGORY());
669
		}
670
		return generic;
671
	}
672
	
673
	private Reference<?> makeDatabase(Map<String, Object> valueMap){
674
		if (logger.isDebugEnabled()){logger.debug("RefType 'Database'");}
675
		Reference database =  ReferenceFactory.newDatabase();
676
		makeStandardMapper(valueMap, database); //?
677
		return database;
678
	}
679
	
680
	private Reference<?> makeJournal(Map<String, Object> valueMap){
681
		if (logger.isDebugEnabled()){logger.debug("RefType 'Journal'");}
682
		Reference journal = ReferenceFactory.newJournal();
683
		
684
		Set<String> omitAttributes = new HashSet<String>();
685
		String series = "series";
686
//		omitAttributes.add(series);
687
		
688
		makeStandardMapper(valueMap, journal, omitAttributes); //issn,placePublished,publisher
689
//		if (valueMap.get(series) != null){
690
//			logger.warn("Series not yet implemented for journal!");
691
//		}
692
		return journal;
693
	}
694
	
695
	private Reference<?> makeBook(
696
				Map<String, Object> valueMap, 
697
				Map<Integer, Reference> refToSave, 
698
				Map<String, Reference> relatedReferences){
699
		if (logger.isDebugEnabled()){logger.debug("RefType 'Book'");}
700
		Reference<?> book = ReferenceFactory.newBook();
701
		Integer refId = (Integer)valueMap.get("refId".toLowerCase());
702
		
703
		//Set bookAttributes = new String[]{"edition", "isbn", "pages","publicationTown","publisher","volume"};
704
		
705
		Set<String> omitAttributes = new HashSet<String>();
706
		String attrSeries = "series";
707
//		omitAttributes.add(attrSeries);
708
		
709
		makeStandardMapper(valueMap, book, omitAttributes);
710
		
711
		//Series (as String)
712
		IPrintSeries printSeries = null;
713
		if (valueMap.get(attrSeries) != null){
714
			String series = (String)valueMap.get("title".toLowerCase());
715
			if (series == null){
716
				String nomTitle = (String)valueMap.get("nomTitleAbbrev".toLowerCase());
717
				series = nomTitle;
718
			}
719
			printSeries = ReferenceFactory.newPrintSeries(series);
720
			logger.info("Implementation of printSeries is preliminary");
721
		}
722
		//Series (as Reference)
723
		if (book.getInSeries() != null && printSeries != null){
724
			logger.warn("Book has series string and inSeries reference. Can not take both. Series string neglected");
725
		}else{
726
			book.setInSeries(printSeries);
727
		}
728
		book.setEditor(null);
729
		return book;
730
		
731
	}
732
	
733
	/**
734
	 * Returns the requested object if it exists in one of both maps. Prefers the refToSaveMap in ambigious cases.
735
	 * @param inRefFkInt
736
	 * @param nomRefToSave
737
	 * @param relatedNomReferences
738
	 * @return
739
	 */
740
	private Reference<?> getReferenceFromMaps(
741
			int inRefFkInt,
742
			Map<Integer, Reference> refToSaveMap,
743
			Map<String, Reference> relatedRefMap) {
744
		Reference<?> result = null;
745
		result = refToSaveMap.get(inRefFkInt);
746
		if (result == null){
747
			result = relatedRefMap.get(String.valueOf(inRefFkInt));
748
		}
749
		return result;
750
	}
751

    
752
	private Reference<?> makePrintSeries(Map<String, Object> valueMap){
753
		if (logger.isDebugEnabled()){logger.debug("RefType 'PrintSeries'");}
754
		Reference<?> printSeries = ReferenceFactory.newPrintSeries();
755
		makeStandardMapper(valueMap, printSeries, null);
756
		return printSeries;
757
	}
758
	
759
	private Reference<?> makeProceedings(Map<String, Object> valueMap){
760
		if (logger.isDebugEnabled()){logger.debug("RefType 'Proceedings'");}
761
		Reference<?> proceedings = ReferenceFactory.newProceedings();
762
		makeStandardMapper(valueMap, proceedings, null);	
763
		return proceedings;
764
	}
765

    
766
	private Reference<?> makeThesis(Map<String, Object> valueMap){
767
		if (logger.isDebugEnabled()){logger.debug("RefType 'Thesis'");}
768
		Reference<?> thesis = ReferenceFactory.newThesis();
769
		makeStandardMapper(valueMap, thesis, null);	
770
		return thesis;
771
	}
772

    
773
	
774
	private Reference<?> makeJournalVolume(Map<String, Object> valueMap){
775
		if (logger.isDebugEnabled()){logger.debug("RefType 'JournalVolume'");}
776
		//Proceedings proceedings = Proceedings.NewInstance();
777
		Reference<?> journalVolume = ReferenceFactory.newGeneric();
778
		makeStandardMapper(valueMap, journalVolume, null);	
779
		logger.warn("Journal volumes not yet implemented. Generic created instead but with errors");
780
		return journalVolume;
781
	}
782
	
783
	private boolean makeStandardMapper(Map<String, Object> valueMap, Reference<?> ref){
784
		return makeStandardMapper(valueMap, ref, null);
785
	}
786

    
787
	
788
	private boolean makeStandardMapper(Map<String, Object> valueMap, CdmBase cdmBase, Set<String> omitAttributes){
789
		boolean result = true;	
790
		for (CdmAttributeMapperBase mapper : classMappers){
791
			if (mapper instanceof CdmSingleAttributeMapperBase){
792
				result &= makeStandardSingleMapper(valueMap, cdmBase, (CdmSingleAttributeMapperBase)mapper, omitAttributes);
793
			}else if (mapper instanceof CdmOneToManyMapper){
794
				result &= makeMultipleValueAddMapper(valueMap, cdmBase, (CdmOneToManyMapper)mapper, omitAttributes);
795
			}else{
796
				logger.error("Unknown mapper type");
797
				result = false;
798
			}
799
		}
800
		return result;
801
	}
802
	
803
	private boolean makeStandardSingleMapper(Map<String, Object> valueMap, CdmBase cdmBase, CdmSingleAttributeMapperBase mapper, Set<String> omitAttributes){
804
		boolean result = true;
805
		if (omitAttributes == null){
806
			omitAttributes = new HashSet<String>();
807
		}
808
		if (mapper instanceof DbImportExtensionMapper){
809
			result &= ((DbImportExtensionMapper)mapper).invoke(valueMap, cdmBase);
810
		}else if (mapper instanceof DbImportMarkerMapper){
811
			result &= ((DbImportMarkerMapper)mapper).invoke(valueMap, cdmBase);
812
		}else{
813
			String sourceAttribute = mapper.getSourceAttributeList().get(0).toLowerCase();
814
			Object value = valueMap.get(sourceAttribute);
815
			if (mapper instanceof CdmUriMapper && value != null){
816
				try {
817
					value = new URI (value.toString());
818
				} catch (URISyntaxException e) {
819
					logger.error("URI syntax exception: " + value.toString());
820
					value = null;
821
				}
822
			}
823
			if (value != null){
824
				String destinationAttribute = mapper.getDestinationAttribute();
825
				if (! omitAttributes.contains(destinationAttribute)){
826
					result &= ImportHelper.addValue(value, cdmBase, destinationAttribute, mapper.getTypeClass(), OVERWRITE, OBLIGATORY);
827
				}
828
			}
829
		}
830
		return result;
831
	}
832

    
833
	
834
	private boolean makeMultipleValueAddMapper(Map<String, Object> valueMap, CdmBase cdmBase, CdmOneToManyMapper<CdmBase, CdmBase, CdmSingleAttributeMapperBase> mapper, Set<String> omitAttributes){
835
		if (omitAttributes == null){
836
			omitAttributes = new HashSet<String>();
837
		}
838
		boolean result = true;
839
		String destinationAttribute = mapper.getSingleAttributeName();
840
		List<Object> sourceValues = new ArrayList<Object>();
841
		List<Class> classes = new ArrayList<Class>();
842
		for (CdmSingleAttributeMapperBase singleMapper : mapper.getSingleMappers()){
843
			String sourceAttribute = singleMapper.getSourceAttribute();
844
			Object value = valueMap.get(sourceAttribute);
845
			sourceValues.add(value);
846
			Class<?> clazz = singleMapper.getTypeClass();
847
			classes.add(clazz);
848
		}
849
		
850
		result &= ImportHelper.addMultipleValues(sourceValues, cdmBase, destinationAttribute, classes, NO_OVERWRITE, OBLIGATORY);
851
		return result;
852
	}
853

    
854
	
855
	private static TeamOrPersonBase<?> getAuthorTeam(String authorString, TeamOrPersonBase<?> nomAuthor){
856
		TeamOrPersonBase<?> result;
857
		if (nomAuthor != null){
858
			result = nomAuthor;
859
		} else if (StringUtils.isNotBlank(authorString)){
860
			//FIXME check for existing team / persons
861
			TeamOrPersonBase<?> team = Team.NewInstance();
862
			team.setNomenclaturalTitle(authorString);
863
			team.setTitleCache(authorString, true);
864
			team.setNomenclaturalTitle(authorString);
865
			result = team;
866
		}else{
867
			result = null;
868
		}
869
		
870
		return result;
871
	}
872
	
873
	
874
	/**
875
	 * @param lowerCase
876
	 * @param config
877
	 * @return
878
	 */
879
	public Set<String> getObligatoryAttributes(boolean lowerCase, BerlinModelImportConfigurator config){
880
		Set<String> result = new HashSet<String>();
881
		Class<ICdmIO>[] ioClassList = config.getIoClassList();
882
		logger.warn("getObligatoryAttributes has been commented because it still needs to be adapted to the new package structure");
883
		result.addAll(Arrays.asList(unclearMappers));
884
		result.addAll(Arrays.asList(createdAndNotesAttributes));
885
		result.addAll(Arrays.asList(operationalAttributes));
886
		CdmIoMapping mapping = new CdmIoMapping();
887
		for (CdmAttributeMapperBase mapper : classMappers){
888
			mapping.addMapper(mapper);
889
		}
890
		result.addAll(mapping.getSourceAttributes());
891
		if (lowerCase){
892
			Set<String> lowerCaseResult = new HashSet<String>();
893
			for (String str : result){
894
				if (str != null){lowerCaseResult.add(str.toLowerCase());}
895
			}
896
			result = lowerCaseResult;
897
		}
898
		return result;
899
	}
900

    
901
	/* (non-Javadoc)
902
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IoStateBase)
903
	 */
904
	@Override
905
	protected boolean doCheck(BerlinModelImportState state){
906
		BerlinModelReferenceImportValidator validator = new BerlinModelReferenceImportValidator();
907
		return validator.validate(state, this);
908
	}
909

    
910
	
911
	/* (non-Javadoc)
912
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IImportConfigurator)
913
	 */
914
	protected boolean isIgnore(BerlinModelImportState state){
915
		return (state.getConfig().getDoReferences() == IImportConfigurator.DO_REFERENCES.NONE);
916
	}
917

    
918
	
919

    
920

    
921
}
(13-13/21)