update factory methods for original sources #1549
[cdmlib.git] / cdmlib-io / src / main / java / eu / etaxonomy / cdm / io / berlinModel / in / BerlinModelReferenceImport.java
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.log4j.Logger;
41 import org.springframework.stereotype.Component;
42
43 import eu.etaxonomy.cdm.common.CdmUtils;
44 import eu.etaxonomy.cdm.io.berlinModel.CdmOneToManyMapper;
45 import eu.etaxonomy.cdm.io.berlinModel.CdmStringMapper;
46 import eu.etaxonomy.cdm.io.berlinModel.CdmUriMapper;
47 import eu.etaxonomy.cdm.io.berlinModel.in.validation.BerlinModelReferenceImportValidator;
48 import eu.etaxonomy.cdm.io.common.ICdmIO;
49 import eu.etaxonomy.cdm.io.common.IImportConfigurator;
50 import eu.etaxonomy.cdm.io.common.ImportHelper;
51 import eu.etaxonomy.cdm.io.common.ResultSetPartitioner;
52 import eu.etaxonomy.cdm.io.common.Source;
53 import eu.etaxonomy.cdm.io.common.mapping.CdmAttributeMapperBase;
54 import eu.etaxonomy.cdm.io.common.mapping.CdmIoMapping;
55 import eu.etaxonomy.cdm.io.common.mapping.CdmSingleAttributeMapperBase;
56 import eu.etaxonomy.cdm.io.common.mapping.DbImportExtensionMapper;
57 import eu.etaxonomy.cdm.io.common.mapping.DbImportMarkerMapper;
58 import eu.etaxonomy.cdm.io.common.mapping.DbSingleAttributeImportMapperBase;
59 import eu.etaxonomy.cdm.model.agent.Team;
60 import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
61 import eu.etaxonomy.cdm.model.common.CdmBase;
62 import eu.etaxonomy.cdm.model.common.ExtensionType;
63 import eu.etaxonomy.cdm.model.common.IdentifiableSource;
64 import eu.etaxonomy.cdm.model.common.Marker;
65 import eu.etaxonomy.cdm.model.common.MarkerType;
66 import eu.etaxonomy.cdm.model.reference.IArticle;
67 import eu.etaxonomy.cdm.model.reference.IBookSection;
68 import eu.etaxonomy.cdm.model.reference.IPrintSeries;
69 import eu.etaxonomy.cdm.model.reference.Reference;
70 import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
71 import eu.etaxonomy.cdm.model.reference.ReferenceType;
72
73 /**
74 * @author a.mueller
75 * @created 20.03.2008
76 * @version 1.0
77 */
78 @Component
79 public class BerlinModelReferenceImport extends BerlinModelImportBase {
80 private static final Logger logger = Logger.getLogger(BerlinModelReferenceImport.class);
81
82 public static final String NOM_REFERENCE_NAMESPACE = "NomReference";
83 public static final String BIBLIO_REFERENCE_NAMESPACE = "BiblioReference";
84
85 public static final UUID REF_DEPOSITED_AT_UUID = UUID.fromString("23ca88c7-ce73-41b2-8ca3-2cb22f013beb");
86 public static final UUID REF_SOURCE_UUID = UUID.fromString("d6432582-2216-4b08-b0db-76f6c1013141");
87 public static final UUID DATE_STRING_UUID = UUID.fromString("e4130eae-606e-4b0c-be4f-e93dc161be7d");
88 public static final UUID IS_PAPER_UUID = UUID.fromString("8a326129-d0d0-4f9d-bbdf-8d86b037c65e");
89
90
91 private int modCount = 1000;
92 private static final String pluralString = "references";
93 private static final String dbTableName = "reference";
94
95
96 public BerlinModelReferenceImport(){
97 super(dbTableName, pluralString);
98 }
99
100 protected void initializeMappers(BerlinModelImportState state){
101 for (CdmAttributeMapperBase mapper: classMappers){
102 if (mapper instanceof DbSingleAttributeImportMapperBase){
103 DbSingleAttributeImportMapperBase singleMapper = (DbSingleAttributeImportMapperBase)mapper;
104 singleMapper.initialize(state, Reference.class);
105 }
106 }
107 return;
108 }
109
110 protected static CdmAttributeMapperBase[] classMappers = new CdmAttributeMapperBase[]{
111 new CdmStringMapper("edition", "edition"),
112 new CdmStringMapper("volume", "volume"),
113 new CdmStringMapper("publisher", "publisher"),
114 new CdmStringMapper("publicationTown", "placePublished"),
115 new CdmStringMapper("isbn", "isbn"),
116 new CdmStringMapper("isbn", "isbn"),
117 new CdmStringMapper("pageString", "pages"),
118 new CdmStringMapper("series", "series"),
119 new CdmStringMapper("issn", "issn"),
120 new CdmUriMapper("url", "uri"),
121 DbImportExtensionMapper.NewInstance("NomStandard", ExtensionType.NOMENCLATURAL_STANDARD()),
122 DbImportExtensionMapper.NewInstance("DateString", DATE_STRING_UUID, "Date String", "Date String", "dates"),
123 DbImportExtensionMapper.NewInstance("RefDepositedAt", REF_DEPOSITED_AT_UUID, "RefDepositedAt", "reference is deposited at", "at"),
124 DbImportExtensionMapper.NewInstance("RefSource", REF_SOURCE_UUID, "RefSource", "reference source", "source"),
125 DbImportMarkerMapper.NewInstance("isPaper", IS_PAPER_UUID, "is paper", "is paper", "paper", false)
126 };
127
128
129 protected static String[] operationalAttributes = new String[]{
130 "refId", "refCache", "nomRefCache", "preliminaryFlag", "inRefFk", "title", "nomTitleAbbrev",
131 "refAuthorString", "nomAuthorTeamFk",
132 "refCategoryFk", "thesisFlag", "informalRefCategory", "idInSource"
133 };
134
135 protected static String[] createdAndNotesAttributes = new String[]{
136 "created_When", "updated_When", "created_Who", "updated_Who", "notes"
137 };
138
139 protected static String[] unclearMappers = new String[]{
140 /*"isPaper",*/ "exportDate",
141 };
142
143 //TODO isPaper
144 //
145
146
147
148 //type to count the references nomReferences that have been created and saved
149 private class RefCounter{
150 RefCounter() {nomRefCount = 0; referenceCount = 0;};
151 int nomRefCount;
152 int referenceCount;
153 public String toString(){return String.valueOf(nomRefCount) + "," +String.valueOf(referenceCount);};
154 }
155
156
157 /* (non-Javadoc)
158 * @see eu.etaxonomy.cdm.io.berlinModel.in.BerlinModelImportBase#getRecordQuery(eu.etaxonomy.cdm.io.berlinModel.in.BerlinModelImportConfigurator)
159 */
160 @Override
161 protected String getRecordQuery(BerlinModelImportConfigurator config) {
162 return null; //not needed
163 }
164
165 @Override
166 protected void doInvoke(BerlinModelImportState state){
167 logger.info("start make " + getPluralString() + " ...");
168
169 boolean success = true;
170 initializeMappers(state);
171 BerlinModelImportConfigurator config = state.getConfig();
172 Source source = config.getSource();
173
174 String strSelectId = " SELECT Reference.RefId as refId ";
175 String strSelectFull =
176 " SELECT Reference.* ,InReference.RefCategoryFk as InRefCategoryFk, RefSource.RefSource " ;
177 String strFrom = " FROM %s " +
178 " LEFT OUTER JOIN Reference as InReference ON InReference.refId = Reference.inRefFk " +
179 " LEFT OUTER JOIN RefSource ON Reference.RefSourceFk = RefSource.RefSourceId " +
180 " WHERE (1=1) ";
181 String strWherePartitioned = " AND (Reference.refId IN ("+ ID_LIST_TOKEN + ") ) ";
182
183 String referenceTable = CdmUtils.Nz(state.getConfig().getReferenceIdTable());
184 referenceTable = referenceTable.isEmpty() ? " Reference" : referenceTable + " as Reference ";
185 String strIdFrom = String.format(strFrom, referenceTable );
186
187 String strSelectIdBase = strSelectId + strIdFrom;
188
189 String referenceFilter = CdmUtils.Nz(state.getConfig().getReferenceIdTable());
190 if (! referenceFilter.isEmpty()){
191 referenceFilter = " AND " + referenceFilter + " ";
192 }
193 referenceFilter = ""; //don't use it for now
194
195 String strIdQueryFirstPath = strSelectId + strIdFrom ;
196 String strIdQuerySecondPath = strSelectId + strIdFrom + " AND (Reference.InRefFk is NOT NULL) ";
197
198 // if (config.getDoReferences() == CONCEPT_REFERENCES){
199 // strIdQueryNoInRef += " AND ( Reference.refId IN ( SELECT ptRefFk FROM PTaxon) ) " + referenceFilter;
200 // }
201
202 String strRecordQuery = strSelectFull + String.format(strFrom, " Reference ") + strWherePartitioned;
203
204 int recordsPerTransaction = config.getRecordsPerTransaction();
205 try{
206 //firstPath
207 ResultSetPartitioner partitioner = ResultSetPartitioner.NewInstance(source, strIdQueryFirstPath, strRecordQuery, recordsPerTransaction);
208 while (partitioner.nextPartition()){
209 partitioner.doPartition(this, state);
210 }
211 logger.info("end make references without in-references ... " + getSuccessString(success));
212 state.setReferenceSecondPath(true);
213
214 // if (config.getDoReferences() == ALL || config.getDoReferences() == NOMENCLATURAL){
215
216 //secondPath
217 partitioner = ResultSetPartitioner.NewInstance(source, strIdQuerySecondPath, strRecordQuery, recordsPerTransaction);
218 while (partitioner.nextPartition()){
219 partitioner.doPartition(this, state);
220 }
221 logger.info("end make references with no 1 in-reference ... " + getSuccessString(success));
222 state.setReferenceSecondPath(false);
223
224 // }
225
226 } catch (SQLException e) {
227 logger.error("SQLException:" + e);
228 state.setUnsuccessfull();
229 return;
230 }
231 logger.info("end make " + getPluralString() + " ... " + getSuccessString(success));
232 if (! success){
233 state.setUnsuccessfull();
234 }
235 return;
236 }
237
238
239
240
241 /* (non-Javadoc)
242 * @see eu.etaxonomy.cdm.io.berlinModel.in.IPartitionedIO#doPartition(eu.etaxonomy.cdm.io.berlinModel.in.ResultSetPartitioner, eu.etaxonomy.cdm.io.berlinModel.in.BerlinModelImportState)
243 */
244 public boolean doPartition(ResultSetPartitioner partitioner, BerlinModelImportState state) {
245 if (state.isReferenceSecondPath()){
246 return doPartitionSecondPath(partitioner, state);
247 }
248 boolean success = true;
249
250 Map<Integer, Reference> nomRefToSave = new HashMap<Integer, Reference>();
251 Map<Integer, Reference> biblioRefToSave = new HashMap<Integer, Reference>();
252
253 Map<String, Reference> relatedNomReferences = partitioner.getObjectMap(NOM_REFERENCE_NAMESPACE);
254 Map<String, Reference> relatedBiblioReferences = partitioner.getObjectMap(BIBLIO_REFERENCE_NAMESPACE);
255
256 BerlinModelImportConfigurator config = state.getConfig();
257
258 try {
259
260 int i = 0;
261 RefCounter refCounter = new RefCounter();
262
263 ResultSet rs = partitioner.getResultSet();
264
265 //for each resultset
266 while (rs.next()){
267 if ((i++ % modCount) == 0 && i!= 1 ){ logger.info("References handled: " + (i-1) + " in round -" );}
268
269 success &= makeSingleReferenceRecord(rs, state, partitioner, biblioRefToSave, nomRefToSave, relatedBiblioReferences, relatedNomReferences, refCounter);
270 } // end resultSet
271
272 //for the concept reference a fixed uuid may be needed -> change uuid
273 Integer sourceSecId = (Integer)config.getSourceSecId();
274 Reference<?> sec = biblioRefToSave.get(sourceSecId);
275 if (sec == null){
276 sec = nomRefToSave.get(sourceSecId);
277 }
278 if (sec != null){
279 sec.setUuid(config.getSecUuid());
280 logger.info("SecUuid changed to: " + config.getSecUuid());
281 }
282
283 //save and store in map
284 logger.info("Save nomenclatural references (" + refCounter.nomRefCount + ")");
285 getReferenceService().saveOrUpdate(nomRefToSave.values());
286 logger.info("Save bibliographical references (" + refCounter.referenceCount +")");
287 getReferenceService().saveOrUpdate(biblioRefToSave.values());
288
289 // }//end resultSetList
290
291 // logger.info("end makeReferences ..." + getSuccessString(success));;
292 return success;
293 } catch (SQLException e) {
294 logger.error("SQLException:" + e);
295 return false;
296 }
297 }
298
299
300
301 /**
302 * Adds the inReference to the according references.
303 * @param partitioner
304 * @param state
305 * @return
306 */
307 private boolean doPartitionSecondPath(ResultSetPartitioner partitioner, BerlinModelImportState state) {
308 boolean success = true;
309
310 Map<Integer, Reference> nomRefToSave = new HashMap<Integer, Reference>();
311 Map<Integer, Reference> biblioRefToSave = new HashMap<Integer, Reference>();
312
313 Map<String, Reference> relatedNomReferences = partitioner.getObjectMap(NOM_REFERENCE_NAMESPACE);
314 Map<String, Reference> relatedBiblioReferences = partitioner.getObjectMap(BIBLIO_REFERENCE_NAMESPACE);
315
316 try {
317 int i = 0;
318 RefCounter refCounter = new RefCounter();
319
320 ResultSet rs = partitioner.getResultSet();
321 //for each resultset
322 while (rs.next()){
323 if ((i++ % modCount) == 0 && i!= 1 ){ logger.info("References handled: " + (i-1) + " in round -" );}
324
325 Integer refId = rs.getInt("refId");
326 Integer inRefFk = rs.getInt("inRefFk");
327
328 if (inRefFk != null){
329
330 Reference<?> thisNomRef = getReferenceOnlyFromMaps(relatedNomReferences, relatedBiblioReferences, String.valueOf(refId));
331 Reference<?> thisBiblioRef = getReferenceOnlyFromMaps(relatedBiblioReferences, relatedNomReferences, String.valueOf(refId));
332
333 Reference<?> nomInReference = relatedNomReferences.get(String.valueOf(inRefFk));
334 Reference<?> biblioInReference = relatedBiblioReferences.get(String.valueOf(inRefFk));
335 boolean inRefExists = false;
336 if (thisNomRef != null){
337 Reference<?> inRef = (nomInReference != null)? nomInReference : biblioInReference;
338 if (inRef == null){
339 logger.warn("No InRef found for nomRef: " + thisNomRef.getTitleCache() + "; RefId: " + refId + "; inRefFK: " + inRefFk);
340 }
341 thisNomRef.setInReference(inRef);
342 nomRefToSave.put(refId, thisNomRef);
343 //remember that an in reference exists
344 inRefExists |= (inRef != null);
345 thisNomRef.setTitleCache(null);
346 thisNomRef.getTitleCache();
347 }
348 if (thisBiblioRef != null){
349 Reference<?> inRef = (biblioInReference != null)? biblioInReference : nomInReference ;
350 if (inRef == null){
351 logger.warn("No InRef found for biblioRef: " + thisBiblioRef.getTitleCache() + "; RefId: " + refId + "; inRefFK: " + inRefFk);
352 }
353 thisBiblioRef.setInReference(inRef);
354 biblioRefToSave.put(refId, thisBiblioRef);
355 //remember that an in reference exists
356 inRefExists |= (inRef != null);
357 thisBiblioRef.setTitleCache(null);
358 thisBiblioRef.getTitleCache();
359 }
360 if (inRefExists == false){
361 logger.warn("No in reference was saved though an 'inRefFk' is available. RefId " + refId);
362 }
363
364 }
365
366 } // end resultSet
367
368 //save and store in map
369 logger.info("Save nomenclatural references (" + refCounter.nomRefCount + ")");
370 getReferenceService().saveOrUpdate(nomRefToSave.values());
371 logger.info("Save bibliographical references (" + refCounter.referenceCount +")");
372 getReferenceService().saveOrUpdate(biblioRefToSave.values());
373
374 // }//end resultSetList
375
376 // logger.info("end makeReferences ..." + getSuccessString(success));;
377 return success;
378 } catch (SQLException e) {
379 logger.error("SQLException:" + e);
380 return false;
381 }
382 }
383
384
385
386 /* (non-Javadoc)
387 * @see eu.etaxonomy.cdm.io.berlinModel.in.IPartitionedIO#getRelatedObjectsForPartition(java.sql.ResultSet)
388 */
389 public Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForPartition(ResultSet rs) {
390 String nameSpace;
391 Class cdmClass;
392 Set<String> idSet;
393
394 Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<Object, Map<String, ? extends CdmBase>>();
395
396 try{
397 Set<String> teamIdSet = new HashSet<String>();
398 Set<String> referenceIdSet = new HashSet<String>();
399
400 while (rs.next()){
401 handleForeignKey(rs, teamIdSet, "NomAuthorTeamFk");
402 handleForeignKey(rs, referenceIdSet, "InRefFk");
403 //TODO only needed in second path but state not available here to check if state is second path
404 handleForeignKey(rs, referenceIdSet, "refId");
405 }
406
407 //team map
408 nameSpace = BerlinModelAuthorTeamImport.NAMESPACE;
409 cdmClass = Team.class;
410 idSet = teamIdSet;
411 Map<String, Team> teamMap = (Map<String, Team>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
412 result.put(nameSpace, teamMap);
413
414
415 //nom reference map
416 nameSpace = NOM_REFERENCE_NAMESPACE;
417 cdmClass = Reference.class;
418 idSet = referenceIdSet;
419 Map<String, Reference> nomRefMap = (Map<String, Reference>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
420 result.put(nameSpace, nomRefMap);
421
422 //biblio reference map
423 nameSpace = BIBLIO_REFERENCE_NAMESPACE;
424 cdmClass = Reference.class;
425 idSet = referenceIdSet;
426 Map<String, Reference> biblioRefMap = (Map<String, Reference>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
427 result.put(nameSpace, biblioRefMap);
428
429 } catch (SQLException e) {
430 throw new RuntimeException(e);
431 }
432 return result;
433 }
434
435
436 /**
437 * Handles a single reference record
438 * @param rs
439 * @param state
440 * @param biblioRefToSave
441 * @param nomRefToSave
442 * @param relatedBiblioReferences
443 * @param relatedNomReferences
444 * @param refCounter
445 * @return
446 */
447 private boolean makeSingleReferenceRecord(
448 ResultSet rs,
449 BerlinModelImportState state,
450 ResultSetPartitioner<BerlinModelImportState> partitioner,
451 Map<Integer, Reference> biblioRefToSave,
452 Map<Integer, Reference> nomRefToSave,
453 Map<String, Reference> relatedBiblioReferences,
454 Map<String, Reference> relatedNomReferences,
455 RefCounter refCounter){
456 boolean success = true;
457
458 Integer refId = null;
459 try {
460 Map<String, Object> valueMap = getValueMap(rs);
461
462 Integer categoryFk = (Integer)valueMap.get("refCategoryFk".toLowerCase());
463 refId = (Integer)valueMap.get("refId".toLowerCase());
464 Boolean thesisFlag = (Boolean)valueMap.get("thesisFlag".toLowerCase());
465
466
467 Reference<?> referenceBase;
468 logger.debug("RefCategoryFk: " + categoryFk);
469
470 if (thesisFlag){
471 referenceBase = makeThesis(valueMap);
472 }else if (categoryFk == REF_JOURNAL){
473 referenceBase = makeJournal(valueMap);
474 }else if(categoryFk == REF_BOOK){
475 referenceBase = makeBook(valueMap, biblioRefToSave, nomRefToSave, relatedBiblioReferences, relatedNomReferences);
476 }else if(categoryFk == REF_DATABASE){
477 referenceBase = makeDatabase(valueMap);
478 }else if(categoryFk == REF_INFORMAL){
479 referenceBase = makeInformal(valueMap);
480 }else if(categoryFk == REF_WEBSITE){
481 referenceBase = makeWebSite(valueMap);
482 }else if(categoryFk == REF_UNKNOWN){
483 referenceBase = makeUnknown(valueMap);
484 }else if(categoryFk == REF_PRINT_SERIES){
485 referenceBase = makePrintSeries(valueMap);
486 }else if(categoryFk == REF_CONFERENCE_PROCEEDINGS){
487 referenceBase = makeProceedings(valueMap);
488 }else if(categoryFk == REF_ARTICLE){
489 referenceBase = makeArticle(valueMap, biblioRefToSave, nomRefToSave, relatedBiblioReferences, relatedNomReferences);
490 }else if(categoryFk == REF_JOURNAL_VOLUME){
491 referenceBase = makeJournalVolume(valueMap);
492 }else if(categoryFk == REF_PART_OF_OTHER_TITLE){
493 referenceBase = makePartOfOtherTitle(valueMap, biblioRefToSave, nomRefToSave, relatedBiblioReferences, relatedNomReferences);
494 }else{
495 logger.warn("Unknown categoryFk (" + categoryFk + "). Create 'Generic instead'");
496 referenceBase = ReferenceFactory.newGeneric();
497 success = false;
498 }
499
500 //refYear
501 String refYear = (String)valueMap.get("refYear".toLowerCase());
502 referenceBase.setDatePublished(ImportHelper.getDatePublished(refYear));
503
504 //created, updated, notes
505 doCreatedUpdatedNotes(state, referenceBase, rs);
506
507 //idInSource
508 String idInSource = (String)valueMap.get("IdInSource".toLowerCase());
509 if (isNotBlank(idInSource)){
510 IdentifiableSource source = IdentifiableSource.NewDataImportInstance(idInSource);
511 source.setIdNamespace("import to Berlin Model");
512 referenceBase.addSource(source);
513 }
514
515 //nom&BiblioReference - must be last because a clone is created
516 success &= makeNomAndBiblioReference(rs, state, partitioner, refId, referenceBase, refCounter,
517 biblioRefToSave, nomRefToSave );
518
519
520 } catch (Exception e) {
521 logger.warn("Reference with BM refId '" + CdmUtils.Nz(refId) + "' threw Exception and could not be saved");
522 e.printStackTrace();
523 success = false;
524 }
525 return success;
526 }
527
528
529 /**
530 * Creates and saves a nom. reference and a biblio. reference after checking necessity
531 * @param rs
532 * @param refId
533 * @param referenceBase
534 * @param refCounter
535 * @param biblioRefToSave
536 * @param nomRefToSave
537 * @param teamMap
538 * @param stores
539 * @return
540 * @throws SQLException
541 */
542 private boolean makeNomAndBiblioReference(
543 ResultSet rs,
544 BerlinModelImportState state,
545 ResultSetPartitioner partitioner,
546 int refId,
547 Reference<?> referenceBase,
548 RefCounter refCounter,
549 Map<Integer, Reference> biblioRefToSave,
550 Map<Integer, Reference> nomRefToSave
551 ) throws SQLException{
552
553 Map<String, Team> teamMap = partitioner.getObjectMap(BerlinModelAuthorTeamImport.NAMESPACE);
554
555 String refCache = rs.getString("refCache");
556 String nomRefCache = rs.getString("nomRefCache");
557 String title = rs.getString("title");
558 String nomTitleAbbrev = rs.getString("nomTitleAbbrev");
559 boolean isPreliminary = rs.getBoolean("PreliminaryFlag");
560 String refAuthorString = rs.getString("refAuthorString");
561 Integer nomAuthorTeamFk = rs.getInt("NomAuthorTeamFk");
562 String strNomAuthorTeamFk = String.valueOf(nomAuthorTeamFk);
563 TeamOrPersonBase<?> nomAuthor = teamMap.get(strNomAuthorTeamFk);
564 Reference nomReference = null;
565
566 boolean hasNomRef = false;
567 boolean hasBiblioRef = false;
568 Reference sourceReference = state.getTransactionalSourceReference();
569
570 //is Nomenclatural Reference
571 if ( (CdmUtils.isNotEmpty(nomRefCache) && isPreliminary) || (CdmUtils.isNotEmpty(nomTitleAbbrev) && ! isPreliminary) ){
572 referenceBase.setTitle(nomTitleAbbrev);
573 TeamOrPersonBase<?> author = getAuthorTeam(refAuthorString , nomAuthor, true);
574 referenceBase.setAuthorTeam(author);
575 //referenceBase.setNomenclaturallyRelevant(true);
576 if (isPreliminary){
577 referenceBase.setTitleCache(nomRefCache, true);
578 }
579 if (! nomRefToSave.containsKey(refId)){
580 if (referenceBase == null){
581 logger.warn("refBase is null");
582 }
583 nomRefToSave.put(refId, referenceBase);
584 }else{
585 logger.warn("Duplicate refId in Berlin Model database. Second reference was not imported !!");
586 }
587
588 // ???
589 // nomRefToSave.put(refId, referenceBase);
590 hasNomRef = true;
591 nomReference = referenceBase;
592 refCounter.nomRefCount++;
593 }
594 //is bibliographical Reference
595 if ((CdmUtils.isNotEmpty(refCache) && isPreliminary && ! refCache.equalsIgnoreCase(nomRefCache))
596 || (CdmUtils.isNotEmpty(title) && ! isPreliminary && ! title.equalsIgnoreCase(nomTitleAbbrev))
597 || hasNomRef == false){
598 if (hasNomRef){
599 referenceBase = (Reference)referenceBase.clone();
600 copyCreatedUpdated(referenceBase, nomReference);
601 }
602 referenceBase.setTitle(title);
603 TeamOrPersonBase author = getAuthorTeam(refAuthorString , nomAuthor, false);
604 referenceBase.setAuthorTeam(author);
605 referenceBase.setNomenclaturallyRelevant(false);
606 if (isPreliminary){
607 referenceBase.setTitleCache(refCache, true);
608 }
609 if (! biblioRefToSave.containsKey(refId)){
610 biblioRefToSave.put(refId, referenceBase);
611 }else{
612 logger.warn("Duplicate refId in Berlin Model database. Second reference was not imported !!");
613 }
614 hasBiblioRef = true;
615
616 //??
617 //biblioRefToSave.put(refId, referenceBase);
618 refCounter.referenceCount++;
619 }
620 //refId
621 if (hasNomRef){
622 ImportHelper.setOriginalSource(nomReference, sourceReference, refId, NOM_REFERENCE_NAMESPACE);
623 }
624 if (hasBiblioRef){
625 ImportHelper.setOriginalSource(referenceBase, sourceReference, refId, BIBLIO_REFERENCE_NAMESPACE);
626 }
627
628 return true;
629
630 }
631
632 /**
633 * Copies the created and updated information from the nomReference to the cloned bibliographic reference
634 * @param referenceBase
635 * @param nomReference
636 */
637 private void copyCreatedUpdated(Reference<?> biblioReference, Reference nomReference) {
638 biblioReference.setCreatedBy(nomReference.getCreatedBy());
639 biblioReference.setCreated(nomReference.getCreated());
640 biblioReference.setUpdatedBy(nomReference.getUpdatedBy());
641 biblioReference.setUpdated(nomReference.getUpdated());
642
643 }
644
645 private Reference<?> makeArticle (Map<String, Object> valueMap, Map<Integer, Reference> biblioRefToSave, Map<Integer, Reference> nomRefToSave, Map<String, Reference> relatedBiblioReferences, Map<String, Reference> relatedNomReferences){
646
647 IArticle article = ReferenceFactory.newArticle();
648 Object inRefFk = valueMap.get("inRefFk".toLowerCase());
649 Integer inRefCategoryFk = (Integer)valueMap.get("inRefCategoryFk".toLowerCase());
650 Integer refId = (Integer)valueMap.get("refId".toLowerCase());
651
652 if (inRefFk != null){
653 if (inRefCategoryFk != REF_JOURNAL){
654 logger.warn("Wrong inrefCategory for Article (refID = " + refId +"). Type must be 'Journal' but was not (RefCategoryFk=" + inRefCategoryFk + "))." +
655 " InReference was added anyway! ");
656 }
657 }else{
658 logger.warn ("Article has no inreference: " + refId);
659 }
660 makeStandardMapper(valueMap, (Reference)article); //url, pages, series, volume
661 return (Reference)article;
662 }
663
664 private Reference<?> makePartOfOtherTitle (Map<String, Object> valueMap, Map<Integer, Reference> biblioRefToSave, Map<Integer, Reference> nomRefToSave, Map<String, Reference> relatedBiblioReferences, Map<String, Reference> relatedNomReferences){
665 Reference<?> result;
666 Object inRefFk = valueMap.get("inRefFk".toLowerCase());
667 Integer inRefCategoryFk = (Integer)valueMap.get("inRefCategoryFk".toLowerCase());
668 Integer refId = (Integer)valueMap.get("refId".toLowerCase());
669
670 if (inRefCategoryFk == null){
671 //null -> error
672 logger.warn("Part-Of-Other-Title has no inRefCategoryFk! RefId = " + refId + ". ReferenceType set to Generic.");
673 result = makeUnknown(valueMap);
674 }else if (inRefFk == null){
675 logger.warn("Part-Of-Other-Title has in in reference: " + refId);
676 result = makeUnknown(valueMap);
677 }else if (inRefCategoryFk == REF_BOOK){
678 //BookSection
679 IBookSection bookSection = ReferenceFactory.newBookSection();
680 result = (Reference<?>)bookSection;
681 }else if (inRefCategoryFk == REF_ARTICLE){
682 //Article
683 //TODO
684 logger.info("Reference (refId = " + refId + ") of type 'part_of_other_title' is part of 'article'." +
685 " There is no specific reference type for such in references yet. Generic reference created instead") ;
686 result = ReferenceFactory.newGeneric();
687 }else if (inRefCategoryFk == REF_JOURNAL){
688 //TODO
689 logger.warn("Reference (refId = " + refId + ") of type 'part_of_other_title' has inReference of type 'journal'." +
690 " This is not allowed! Generic reference created instead") ;
691 result = ReferenceFactory.newGeneric();
692 result.addMarker(Marker.NewInstance(MarkerType.TO_BE_CHECKED(), true));
693 }else{
694 logger.warn("InReference type (catFk = " + inRefCategoryFk + ") of part-of-reference not recognized for refId " + refId + "." +
695 " Create 'Generic' reference instead");
696 result = ReferenceFactory.newGeneric();
697 }
698 makeStandardMapper(valueMap, result); //url, pages
699 return result;
700 }
701
702
703 /**
704 * @param inRefFkInt
705 * @param biblioRefToSave
706 * @param nomRefToSave
707 * @param relatedBiblioReferences
708 * @param relatedNomReferences
709 * @return
710 */
711 private boolean existsInMapOrToSave(Integer inRefFkInt, Map<Integer, Reference> biblioRefToSave, Map<Integer, Reference> nomRefToSave, Map<String, Reference> relatedBiblioReferences, Map<String, Reference> relatedNomReferences) {
712 boolean result = false;
713 if (inRefFkInt == null){
714 return false;
715 }
716 result |= nomRefToSave.containsKey(inRefFkInt);
717 result |= biblioRefToSave.containsKey(inRefFkInt);
718 result |= relatedBiblioReferences.containsKey(String.valueOf(inRefFkInt));
719 result |= relatedNomReferences.containsKey(String.valueOf(inRefFkInt));
720 return result;
721 }
722
723 private Reference<?> makeWebSite(Map<String, Object> valueMap){
724 if (logger.isDebugEnabled()){logger.debug("RefType 'Website'");}
725 Reference<?> webPage = ReferenceFactory.newWebPage();
726 makeStandardMapper(valueMap, webPage); //placePublished, publisher
727 return webPage;
728 }
729
730 private Reference<?> makeUnknown(Map<String, Object> valueMap){
731 if (logger.isDebugEnabled()){logger.debug("RefType 'Unknown'");}
732 Reference<?> generic = ReferenceFactory.newGeneric();
733 // generic.setSeries(series);
734 makeStandardMapper(valueMap, generic); //pages, placePublished, publisher, series, volume
735 return generic;
736 }
737
738 private Reference<?> makeInformal(Map<String, Object> valueMap){
739 if (logger.isDebugEnabled()){logger.debug("RefType 'Informal'");}
740 Reference<?> generic = ReferenceFactory.newGeneric();
741 // informal.setSeries(series);
742 makeStandardMapper(valueMap, generic);//editor, pages, placePublished, publisher, series, volume
743 String informal = (String)valueMap.get("InformalRefCategory".toLowerCase());
744 if (CdmUtils.isNotEmpty(informal) ){
745 generic.addExtension(informal, ExtensionType.INFORMAL_CATEGORY());
746 }
747 return generic;
748 }
749
750 private Reference<?> makeDatabase(Map<String, Object> valueMap){
751 if (logger.isDebugEnabled()){logger.debug("RefType 'Database'");}
752 Reference database = ReferenceFactory.newDatabase();
753 makeStandardMapper(valueMap, database); //?
754 return database;
755 }
756
757 private Reference<?> makeJournal(Map<String, Object> valueMap){
758 if (logger.isDebugEnabled()){logger.debug("RefType 'Journal'");}
759 Reference journal = ReferenceFactory.newJournal();
760
761 Set<String> omitAttributes = new HashSet<String>();
762 String series = "series";
763 // omitAttributes.add(series);
764
765 makeStandardMapper(valueMap, journal, omitAttributes); //issn,placePublished,publisher
766 // if (valueMap.get(series) != null){
767 // logger.warn("Series not yet implemented for journal!");
768 // }
769 return journal;
770 }
771
772 private Reference<?> makeBook(
773 Map<String, Object> valueMap,
774 Map<Integer, Reference> biblioRefToSave,
775 Map<Integer, Reference> nomRefToSave,
776 Map<String, Reference> relatedBiblioReferences,
777 Map<String, Reference> relatedNomReferences){
778 if (logger.isDebugEnabled()){logger.debug("RefType 'Book'");}
779 Reference<?> book = ReferenceFactory.newBook();
780 Integer refId = (Integer)valueMap.get("refId".toLowerCase());
781
782 //Set bookAttributes = new String[]{"edition", "isbn", "pages","publicationTown","publisher","volume"};
783
784 Set<String> omitAttributes = new HashSet<String>();
785 String attrSeries = "series";
786 // omitAttributes.add(attrSeries);
787
788 makeStandardMapper(valueMap, book, omitAttributes);
789
790 //Series (as String)
791 IPrintSeries printSeries = null;
792 if (valueMap.get(attrSeries) != null){
793 String series = (String)valueMap.get("title".toLowerCase());
794 if (series == null){
795 String nomTitle = (String)valueMap.get("nomTitleAbbrev".toLowerCase());
796 series = nomTitle;
797 }
798 printSeries = ReferenceFactory.newPrintSeries(series);
799 logger.info("Implementation of printSeries is preliminary");
800 }
801 Object inRefFk = valueMap.get("inRefFk".toLowerCase());
802 //Series (as Reference)
803 if (inRefFk != null && false){ //&&false added for first/second path implementation, following code may be removed if this is successful
804 int inRefFkInt = (Integer)inRefFk;
805 if (existsInMapOrToSave(inRefFkInt, biblioRefToSave, nomRefToSave, relatedBiblioReferences, relatedNomReferences)){
806 Reference<?> inSeries = getReferenceFromMaps(inRefFkInt, nomRefToSave, relatedNomReferences);
807 if (inSeries == null){
808 inSeries = getReferenceFromMaps(inRefFkInt, biblioRefToSave, relatedBiblioReferences);
809 logger.info("inSeries (" + inRefFkInt + ") found in referenceStore instead of nomRefStore.");
810 nomRefToSave.put(inRefFkInt, inSeries);
811 }
812 if (inSeries == null){
813 logger.warn("inSeries for " + inRefFkInt + " is null. "+
814 " InReference relation could not be set");;
815 //}else if (PrintSeries.class.isAssignableFrom(inSeries.getClass())){
816 }else if (inSeries.getType().equals(ReferenceType.PrintSeries)){
817 book.setInSeries((IPrintSeries)inSeries);
818 //TODO
819 }else{
820 logger.warn("inSeries is not of type PrintSeries but of type " + inSeries.getType().getMessage() +
821 ". In-reference relation could not be set for refId " + refId + " and inRefFk " + inRefFk);
822 }
823 }else{
824 logger.error("PrintSeries (refId = " + inRefFkInt + ") for book (refID = " + refId +") could not be found in nomRefStore. Inconsistency error. ");
825 //success = false;
826 }
827 }
828 if (book.getInSeries() != null && printSeries != null){
829 logger.warn("Book has series string and inSeries reference. Can not take both. Series string neglected");
830 }else{
831 book.setInSeries(printSeries);
832 }
833 book.setEditor(null);
834 return book;
835
836 }
837
838 /**
839 * Returns the requested object if it exists in one of both maps. Prefers the refToSaveMap in ambigious cases.
840 * @param inRefFkInt
841 * @param nomRefToSave
842 * @param relatedNomReferences
843 * @return
844 */
845 private Reference<?> getReferenceFromMaps(
846 int inRefFkInt,
847 Map<Integer, Reference> refToSaveMap,
848 Map<String, Reference> relatedRefMap) {
849 Reference<?> result = null;
850 result = refToSaveMap.get(inRefFkInt);
851 if (result == null){
852 result = relatedRefMap.get(String.valueOf(inRefFkInt));
853 }
854 return result;
855 }
856
857 private Reference<?> makePrintSeries(Map<String, Object> valueMap){
858 if (logger.isDebugEnabled()){logger.debug("RefType 'PrintSeries'");}
859 Reference<?> printSeries = ReferenceFactory.newPrintSeries();
860 makeStandardMapper(valueMap, printSeries, null);
861 return printSeries;
862 }
863
864 private Reference<?> makeProceedings(Map<String, Object> valueMap){
865 if (logger.isDebugEnabled()){logger.debug("RefType 'Proceedings'");}
866 Reference<?> proceedings = ReferenceFactory.newProceedings();
867 makeStandardMapper(valueMap, proceedings, null);
868 return proceedings;
869 }
870
871 private Reference<?> makeThesis(Map<String, Object> valueMap){
872 if (logger.isDebugEnabled()){logger.debug("RefType 'Thesis'");}
873 Reference<?> thesis = ReferenceFactory.newThesis();
874 makeStandardMapper(valueMap, thesis, null);
875 return thesis;
876 }
877
878
879 private Reference<?> makeJournalVolume(Map<String, Object> valueMap){
880 if (logger.isDebugEnabled()){logger.debug("RefType 'JournalVolume'");}
881 //Proceedings proceedings = Proceedings.NewInstance();
882 Reference<?> journalVolume = ReferenceFactory.newGeneric();
883 makeStandardMapper(valueMap, journalVolume, null);
884 logger.warn("Journal volumes not yet implemented. Generic created instead but with errors");
885 return journalVolume;
886 }
887
888 private boolean makeStandardMapper(Map<String, Object> valueMap, Reference<?> ref){
889 return makeStandardMapper(valueMap, ref, null);
890 }
891
892
893 private boolean makeStandardMapper(Map<String, Object> valueMap, CdmBase cdmBase, Set<String> omitAttributes){
894 boolean result = true;
895 for (CdmAttributeMapperBase mapper : classMappers){
896 if (mapper instanceof CdmSingleAttributeMapperBase){
897 result &= makeStandardSingleMapper(valueMap, cdmBase, (CdmSingleAttributeMapperBase)mapper, omitAttributes);
898 }else if (mapper instanceof CdmOneToManyMapper){
899 result &= makeMultipleValueAddMapper(valueMap, cdmBase, (CdmOneToManyMapper)mapper, omitAttributes);
900 }else{
901 logger.error("Unknown mapper type");
902 result = false;
903 }
904 }
905 return result;
906 }
907
908 private boolean makeStandardSingleMapper(Map<String, Object> valueMap, CdmBase cdmBase, CdmSingleAttributeMapperBase mapper, Set<String> omitAttributes){
909 boolean result = true;
910 if (omitAttributes == null){
911 omitAttributes = new HashSet<String>();
912 }
913 if (mapper instanceof DbImportExtensionMapper){
914 result &= ((DbImportExtensionMapper)mapper).invoke(valueMap, cdmBase);
915 }else if (mapper instanceof DbImportMarkerMapper){
916 result &= ((DbImportMarkerMapper)mapper).invoke(valueMap, cdmBase);
917 }else{
918 String sourceAttribute = mapper.getSourceAttributeList().get(0).toLowerCase();
919 Object value = valueMap.get(sourceAttribute);
920 if (mapper instanceof CdmUriMapper && value != null){
921 try {
922 value = new URI (value.toString());
923 } catch (URISyntaxException e) {
924 logger.error("URI syntax exception: " + value.toString());
925 value = null;
926 }
927 }
928 if (value != null){
929 String destinationAttribute = mapper.getDestinationAttribute();
930 if (! omitAttributes.contains(destinationAttribute)){
931 result &= ImportHelper.addValue(value, cdmBase, destinationAttribute, mapper.getTypeClass(), OVERWRITE, OBLIGATORY);
932 }
933 }
934 }
935 return result;
936 }
937
938
939 private boolean makeMultipleValueAddMapper(Map<String, Object> valueMap, CdmBase cdmBase, CdmOneToManyMapper<CdmBase, CdmBase, CdmSingleAttributeMapperBase> mapper, Set<String> omitAttributes){
940 if (omitAttributes == null){
941 omitAttributes = new HashSet<String>();
942 }
943 boolean result = true;
944 String destinationAttribute = mapper.getSingleAttributeName();
945 List<Object> sourceValues = new ArrayList<Object>();
946 List<Class> classes = new ArrayList<Class>();
947 for (CdmSingleAttributeMapperBase singleMapper : mapper.getSingleMappers()){
948 String sourceAttribute = singleMapper.getSourceAttribute();
949 Object value = valueMap.get(sourceAttribute);
950 sourceValues.add(value);
951 Class<?> clazz = singleMapper.getTypeClass();
952 classes.add(clazz);
953 }
954
955 result &= ImportHelper.addMultipleValues(sourceValues, cdmBase, destinationAttribute, classes, NO_OVERWRITE, OBLIGATORY);
956 // //only for testing
957 // if (cdmBase instanceof PublicationBase){
958 // PublicationBase pub = ((PublicationBase)cdmBase);
959 // pub.addPublisher("A new publisher for " + pub.getTitleCache(), "A nice place");
960 // }
961 return result;
962 }
963
964
965 private static TeamOrPersonBase<?> getAuthorTeam(String authorString, TeamOrPersonBase<?> nomAuthor, boolean preferNomeclaturalAuthor){
966 TeamOrPersonBase<?> result;
967 if (preferNomeclaturalAuthor){
968 if (nomAuthor != null){
969 result = nomAuthor;
970 }else{
971 if (CdmUtils.isEmpty(authorString)){
972 result = null;
973 }else{
974 TeamOrPersonBase<?> team = Team.NewInstance();
975 //TODO which one to use??
976 team.setNomenclaturalTitle(authorString);
977 team.setTitleCache(authorString, true);
978 result = team;
979 }
980 }
981 }else{ //prefer bibliographic
982 if (CdmUtils.isNotEmpty(authorString)){
983 TeamOrPersonBase<?> team = Team.NewInstance();
984 //TODO which one to use??
985 team.setNomenclaturalTitle(authorString);
986 team.setTitleCache(authorString, true);
987 result = team;
988 }else{
989 result = nomAuthor;
990 }
991 }
992 return result;
993 }
994
995
996 /**
997 * @param lowerCase
998 * @param config
999 * @return
1000 */
1001 public Set<String> getObligatoryAttributes(boolean lowerCase, BerlinModelImportConfigurator config){
1002 Set<String> result = new HashSet<String>();
1003 Class<ICdmIO>[] ioClassList = config.getIoClassList();
1004 logger.warn("getObligatoryAttributes has been commented because it still needs to be adapted to the new package structure");
1005 result.addAll(Arrays.asList(unclearMappers));
1006 result.addAll(Arrays.asList(createdAndNotesAttributes));
1007 result.addAll(Arrays.asList(operationalAttributes));
1008 CdmIoMapping mapping = new CdmIoMapping();
1009 for (CdmAttributeMapperBase mapper : classMappers){
1010 mapping.addMapper(mapper);
1011 }
1012 result.addAll(mapping.getSourceAttributes());
1013 if (lowerCase){
1014 Set<String> lowerCaseResult = new HashSet<String>();
1015 for (String str : result){
1016 if (str != null){lowerCaseResult.add(str.toLowerCase());}
1017 }
1018 result = lowerCaseResult;
1019 }
1020 return result;
1021 }
1022
1023 /* (non-Javadoc)
1024 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IoStateBase)
1025 */
1026 @Override
1027 protected boolean doCheck(BerlinModelImportState state){
1028 BerlinModelReferenceImportValidator validator = new BerlinModelReferenceImportValidator();
1029 return validator.validate(state, this);
1030 }
1031
1032
1033 /* (non-Javadoc)
1034 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IImportConfigurator)
1035 */
1036 protected boolean isIgnore(BerlinModelImportState state){
1037 return (state.getConfig().getDoReferences() == IImportConfigurator.DO_REFERENCES.NONE);
1038 }
1039
1040
1041
1042
1043 }