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