3 * Copyright (C) 2009 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
10 package eu
.etaxonomy
.cdm
.io
.pesi
.out
;
12 import static java
.util
.EnumSet
.of
;
14 import java
.sql
.Connection
;
15 import java
.sql
.PreparedStatement
;
16 import java
.sql
.SQLException
;
17 import java
.util
.Arrays
;
18 import java
.util
.HashSet
;
19 import java
.util
.List
;
23 import org
.apache
.log4j
.Logger
;
24 import org
.springframework
.stereotype
.Component
;
25 import org
.springframework
.transaction
.TransactionStatus
;
27 import eu
.etaxonomy
.cdm
.io
.berlinModel
.BerlinModelTransformer
;
28 import eu
.etaxonomy
.cdm
.io
.common
.DbExportStateBase
;
29 import eu
.etaxonomy
.cdm
.io
.common
.Source
;
30 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.UndefinedTransformerMethodException
;
31 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.CollectionExportMapping
;
32 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbAreaMapper
;
33 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbDescriptionElementTaxonMapper
;
34 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbDistributionStatusMapper
;
35 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbExportIgnoreMapper
;
36 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbExportNotYetImplementedMapper
;
37 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbLanguageMapper
;
38 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbObjectMapper
;
39 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbOriginalNameMapper
;
40 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbSimpleFilterMapper
;
41 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbSingleSourceMapper
;
42 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbStringMapper
;
43 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbTextDataMapper
;
44 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.IdMapper
;
45 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.MethodMapper
;
46 import eu
.etaxonomy
.cdm
.io
.profiler
.ProfilerController
;
47 //import eu.etaxonomy.cdm.io.profiler.ProfilerController;
48 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
49 import eu
.etaxonomy
.cdm
.model
.common
.Extension
;
50 import eu
.etaxonomy
.cdm
.model
.common
.ExtensionType
;
51 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
52 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
53 import eu
.etaxonomy
.cdm
.model
.common
.LanguageString
;
54 import eu
.etaxonomy
.cdm
.model
.common
.Marker
;
55 import eu
.etaxonomy
.cdm
.model
.common
.MarkerType
;
56 import eu
.etaxonomy
.cdm
.model
.description
.CommonTaxonName
;
57 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionBase
;
58 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
59 import eu
.etaxonomy
.cdm
.model
.description
.Distribution
;
60 import eu
.etaxonomy
.cdm
.model
.description
.Feature
;
61 import eu
.etaxonomy
.cdm
.model
.description
.IndividualsAssociation
;
62 import eu
.etaxonomy
.cdm
.model
.description
.TaxonInteraction
;
63 import eu
.etaxonomy
.cdm
.model
.description
.TextData
;
64 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
65 import eu
.etaxonomy
.cdm
.model
.location
.TdwgArea
;
66 import eu
.etaxonomy
.cdm
.model
.name
.NonViralName
;
67 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
69 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
70 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
72 * The export class for {@link eu.etaxonomy.cdm.model.description.DescriptionElementBase DescriptionElements}.<p>
73 * Inserts into DataWarehouse database table <code>Note</code>.<p>
74 * It is divided into two phases:<ul>
75 * <li>Phase 1: Export of DescriptionElements as Notes.
76 * <li>Phase 2: Export of TaxonName extensions <code>taxComment</code>, <code>fauComment</code> and <code>fauExtraCodes</code> as Notes.</ul>
82 public class PesiDescriptionExport
extends PesiExportBase
{
83 private static final Logger logger
= Logger
.getLogger(PesiDescriptionExport
.class);
85 private static final Class
<?
extends CdmBase
> standardMethodParameter
= DescriptionElementBase
.class;
87 private static int modCount
= 1000;
88 private static final String dbNoteTableName
= "Note";
89 private static final String dbOccurrenceTableName
= "Occurrence";
90 private static final String dbVernacularTableName
= "CommonName";
91 private static final String dbImageTableName
= "Image";
92 private static final String dbAdditionalSourceTableName
= "AdditionalTaxonSource";
93 private static final String pluralString
= "attached infos";
94 private static final String parentPluralString
= "Taxa";
97 private static int countDescriptions
;
98 private static int countTaxa
;
99 private static int countDistribution
;
100 private static int countAdditionalSources
;
101 private static int countImages
;
102 private static int countNotes
;
104 private static int countCommonName
;
105 private static int countOccurrence
;
106 private static int countOthers
;
108 public PesiDescriptionExport() {
113 * @see eu.etaxonomy.cdm.io.common.DbExportBase#getStandardMethodParameter()
116 public Class
<?
extends CdmBase
> getStandardMethodParameter() {
117 return standardMethodParameter
;
121 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IoStateBase)
124 protected boolean doCheck(PesiExportState state
) {
125 boolean result
= true;
130 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doInvoke(eu.etaxonomy.cdm.io.common.IoStateBase)
133 protected void doInvoke(PesiExportState state
) {
135 logger
.info("*** Started Making " + pluralString
+ " ...");
137 // Stores whether this invoke was successful or not.
138 boolean success
= true;
140 // PESI: Clear the database table Note.
144 success
&= doPhase01(state
);
147 logger
.info("PHASE 2...");
148 success
&= doPhase02(state
);
151 logger
.info("*** Finished Making " + pluralString
+ " ..." + getSuccessString(success
));
154 state
.setUnsuccessfull();
157 } catch (SQLException e
) {
159 logger
.error(e
.getMessage());
160 state
.setUnsuccessfull();
164 //PHASE 01: Description Elements
165 private boolean doPhase01(PesiExportState state
) throws SQLException
{
166 logger
.info("PHASE 1...");
169 boolean success
= true;
170 int limit
= state
.getConfig().getLimitSave();
172 // Get specific mappings: (CDM) DescriptionElement -> (PESI) Note
173 PesiExportMapping notesMapping
= getNotesMapping();
174 notesMapping
.initialize(state
);
176 // Get specific mappings: (CDM) DescriptionElement -> (PESI) Occurrence
177 PesiExportMapping occurrenceMapping
= getOccurrenceMapping();
178 occurrenceMapping
.initialize(state
);
180 // Get specific mappings: (CDM) DescriptionElement -> (PESI) Additional taxon source
181 PesiExportMapping addittionalSourceMapping
= getAdditionalTaxonSourceMapping();
182 addittionalSourceMapping
.initialize(state
);
184 // Get specific mappings: (CDM) DescriptionElement -> (PESI) Additional taxon source
185 PesiExportMapping vernacularMapping
= getVernacularNamesMapping();
186 vernacularMapping
.initialize(state
);
188 // Get specific mappings: (CDM) DescriptionElement -> (PESI) Additional taxon source
189 PesiExportMapping imageMapping
= getImageMapping();
190 imageMapping
.initialize(state
);
193 List
<Taxon
> list
= null;
195 TransactionStatus txStatus
= startTransaction(true);
196 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
197 List
<String
> propPath
= Arrays
.asList(new String
[]{"descriptions.elements.*"});
199 logger
.debug("Start snapshot, before starting loop");
200 ProfilerController
.memorySnapshot();
202 int partitionCount
= 0;
203 while ((list
= getNextTaxonPartition(Taxon
.class, limit
, partitionCount
++, propPath
)) != null ) {
205 logger
.info("Fetched " + list
.size() + " " + pluralString
+ ". Exporting...");
207 logger
.debug("Start snapshot, beginning of loop, fetched " + list
.size() + " " + pluralString
);
208 ProfilerController
.memorySnapshot();
210 for (Taxon taxon
: list
) {
212 doCount(count
++, modCount
, pluralString
);
213 success
&= handleSingleTaxon(taxon
, state
, notesMapping
, occurrenceMapping
, addittionalSourceMapping
, vernacularMapping
, imageMapping
);
216 state
.setCurrentTaxon(null);
218 // Commit transaction
219 commitTransaction(txStatus
);
220 logger
.info("Exported " + (count
- pastCount
) + " " + pluralString
+ ". Total: " + count
);
224 txStatus
= startTransaction(true);
225 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") for description import ...");
226 logger
.debug("Start snapshot, end of loop, fetched " + " " + pluralString
);
227 ProfilerController
.memorySnapshot();
230 // //name descriptions
231 // while ((list = getNextNameDescriptionPartition( limit, partitionCount++, propPath )) != null ) {
233 // logger.info("Fetched " + list.size() + " " + pluralString + ". Exporting...");
236 // for (Taxon taxon : list) {
238 // doCount(count++, modCount, pluralString);
239 // success &= handleSingleTaxon(taxon, state, notesMapping, occurrenceMapping, addittionalSourceMapping, vernacularMapping, imageMapping);
241 // state.setCurrentTaxon(null);
243 // // Commit transaction
244 // commitTransaction(txStatus);
245 // logger.info("Exported " + (count - pastCount) + " " + pluralString + ". Total: " + count);
246 // pastCount = count;
248 // // Start transaction
249 // txStatus = startTransaction(true);
250 // logger.info("Started new transaction. Fetching some " + pluralString + " (max: " + limit + ") for description import ...");
256 logger
.info("No " + pluralString
+ " left to fetch.");
257 logger
.info("Partition: " + partitionCount
);
258 logger
.info("Taxa: " + countTaxa
);
259 logger
.info("Desc: " + countDescriptions
);
260 logger
.info("Distr: " + countDistribution
);
261 logger
.info("Occur: " + countOccurrence
);
262 logger
.info("Commons: " + countCommonName
);
263 logger
.info("AddSrc: " + countAdditionalSources
);
264 logger
.info("Images: " + countImages
);
265 logger
.info("Notes: " + countNotes
);
266 logger
.info("Others: " + countOthers
);
271 // Commit transaction
272 commitTransaction(txStatus
);
273 logger
.debug("Committed transaction.");
277 private boolean handleSingleTaxon(Taxon taxon
, PesiExportState state
, PesiExportMapping notesMapping
, PesiExportMapping occurrenceMapping
,
278 PesiExportMapping addittionalSourceMapping
, PesiExportMapping vernacularMapping
, PesiExportMapping imageMapping
) throws SQLException
{
279 boolean success
= true;
280 Set
<DescriptionBase
<?
>> descriptions
= new HashSet
<DescriptionBase
<?
>>();
281 descriptions
.addAll(taxon
.getDescriptions());
283 //FIXME incorrect as this creates duplicates
284 descriptions
.addAll(taxon
.getName().getDescriptions());
286 state
.setCurrentTaxon(taxon
);
287 for (DescriptionBase
<?
> desc
: descriptions
){
290 boolean isImageGallery
= desc
.isImageGallery();
291 for (DescriptionElementBase element
: desc
.getElements()){
292 success
&= handleDescriptionElement(state
, notesMapping
, occurrenceMapping
, vernacularMapping
, imageMapping
,
293 isImageGallery
, element
);
299 private boolean handleDescriptionElement(PesiExportState state
, PesiExportMapping notesMapping
,
300 PesiExportMapping occurrenceMapping
, PesiExportMapping vernacularMapping
, PesiExportMapping imageMapping
,
301 boolean isImageGallery
, DescriptionElementBase element
) throws SQLException
{
303 boolean success
= true;
307 success
&= imageMapping
.invoke(element
);
308 }else if (isCommonName(element
)){
310 if (element
.isInstanceOf(TextData
.class)){
313 success
&= vernacularMapping
.invoke(element
);
315 }else if (isOccurrence(element
)){
317 Distribution distribution
= CdmBase
.deproxy(element
, Distribution
.class);
318 MarkerType markerType
= getUuidMarkerType(PesiTransformer
.uuidMarkerTypeHasNoLastAction
, state
);
320 distribution
.addMarker(Marker
.NewInstance(markerType
, true));
321 if (isPesiDistribution(state
, distribution
)){
323 success
&=occurrenceMapping
.invoke(element
);
325 }else if (isAdditionalTaxonSource(element
)){
326 countAdditionalSources
++;
327 // success &= addittionalSourceMapping.invoke(element);
328 }else if (isPesiNote(element
)){
330 success
&= notesMapping
.invoke(element
);
333 String featureTitle
= element
.getFeature() == null ?
"no feature" :element
.getFeature().getTitleCache();
334 logger
.warn("Description element type not yet handled by PESI export: " + element
.getUuid() + ", " + element
.getClass() + ", " + featureTitle
);
337 } catch (Exception e
) {
338 logger
.warn("Exception appeared in description element handling: " + e
);
344 private boolean isPesiDistribution(PesiExportState state
, Distribution distribution
) {
345 //currently we use the E+M summary status to decide if a distribution should be exported
346 if (distribution
.getStatus() == null){
350 //...this may change in future so we keep the following code
353 NamedArea area
= distribution
.getArea();
355 logger
.warn("Area is null for distribution " + distribution
.getUuid());
357 }else if (area
.getUuid().equals(BerlinModelTransformer
.euroMedUuid
)){
358 //E+M area only holds endemic status information and therefore is not exported to PESI
360 }else if (area
.equals(TdwgArea
.getAreaByTdwgAbbreviation("1"))){
361 //Europe area never holds status information (may probably be deleted in E+M)
363 // }else if (area.equals(TdwgArea.getAreaByTdwgAbbreviation("21"))){
364 // //Macaronesia records should not be exported to PESI
366 // //TODO exclude Russion areas Rs*, and maybe ohters
370 if (state
.getTransformer().getKeyByNamedArea(area
) == null){
371 logger
.warn("Area not available in PESI transformer " + area
.getTitleCache() + ", " + area
.getRepresentation(Language
.ENGLISH()).getAbbreviatedLabel());
374 } catch (UndefinedTransformerMethodException e1
) {
375 logger
.warn("Area not available in PESI transformer " + area
.getTitleCache());
382 // PresenceAbsenceTermBase<?> status = distribution.getStatus();
383 // if (status == null){
384 // logger.warn("No status for distribution: " + distribution.getUuid());
388 // key = (Integer)state.getTransformer().getKeyByPresenceAbsenceTerm(status);
392 // logger.warn("PresenceAbsenceTerm " + status.getTitleCache() + "not handled in transformer");
395 // } catch (UndefinedTransformerMethodException e) {
396 // logger.warn("PresenceAbsenceTerm " + status.getTitleCache() + "not handled in transformer");
401 private boolean isPesiNote(DescriptionElementBase element
) {
402 return (getNoteCategoryFk(element
) != null);
405 private boolean isAdditionalTaxonSource(DescriptionElementBase element
) {
406 Feature feature
= element
.getFeature();
407 if (feature
== null){
410 return (feature
.equals(Feature
.CITATION()));
413 private boolean isOccurrence(DescriptionElementBase element
) {
414 Feature feature
= element
.getFeature();
415 if (feature
== null){
418 if (feature
.equals(Feature
.DISTRIBUTION())){
420 }else if (element
.isInstanceOf(Distribution
.class)){
421 logger
.warn("Description element has class 'Distribution' but has no feature 'Distribution'");
428 private boolean isCommonName(DescriptionElementBase element
) {
429 Feature feature
= element
.getFeature();
430 if (feature
== null){
433 return (feature
.equals(Feature
.COMMON_NAME()));
436 //PHASE 02: Name extensions
437 private boolean doPhase02(PesiExportState state
) {
438 TransactionStatus txStatus
;
439 boolean success
= true;
441 // Get the limit for objects to save within a single transaction.
442 int limit
= state
.getConfig().getLimitSave();
444 txStatus
= startTransaction(true);
445 ExtensionType taxCommentExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.taxCommentUuid
);
446 ExtensionType fauCommentExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.fauCommentUuid
);
447 ExtensionType fauExtraCodesExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.fauExtraCodesUuid
);
448 List
<TaxonNameBase
> taxonNameList
= null;
452 Connection connection
= state
.getConfig().getDestination().getConnection();
453 logger
.info("Started new transaction. Fetching some " + parentPluralString
+ " first (max: " + limit
+ ") ...");
454 logger
.warn("TODO handle extensions on taxon level, not name level (");
455 while ((taxonNameList
= getNameService().list(null, limit
, count
, null, null)).size() > 0) {
457 logger
.info("Fetched " + taxonNameList
.size() + " names. Exporting...");
458 for (TaxonNameBase
<?
,?
> taxonName
: taxonNameList
) {
459 Set
<Extension
> extensions
= taxonName
.getExtensions();
460 for (Extension extension
: extensions
) {
461 if (extension
.getType().equals(taxCommentExtensionType
)) {
462 String taxComment
= extension
.getValue();
463 invokeNotes(taxComment
,
464 PesiTransformer
.getNoteCategoryFk(PesiTransformer
.taxCommentUuid
),
465 PesiTransformer
.getNoteCategoryCache(PesiTransformer
.taxCommentUuid
),
466 null, null, getTaxonKey(taxonName
, state
),connection
);
467 } else if (extension
.getType().equals(fauCommentExtensionType
)) {
468 String fauComment
= extension
.getValue();
469 invokeNotes(fauComment
,
470 PesiTransformer
.getNoteCategoryFk(PesiTransformer
.fauCommentUuid
),
471 PesiTransformer
.getNoteCategoryCache(PesiTransformer
.fauCommentUuid
),
472 null, null, getTaxonKey(taxonName
, state
),connection
);
473 } else if (extension
.getType().equals(fauExtraCodesExtensionType
)) {
474 String fauExtraCodes
= extension
.getValue();
475 invokeNotes(fauExtraCodes
,
476 PesiTransformer
.getNoteCategoryFk(PesiTransformer
.fauExtraCodesUuid
),
477 PesiTransformer
.getNoteCategoryCache(PesiTransformer
.fauExtraCodesUuid
),
478 null, null, getTaxonKey(taxonName
, state
),connection
);
482 doCount(count
++, modCount
, pluralString
);
485 // Commit transaction
486 commitTransaction(txStatus
);
487 logger
.debug("Committed transaction.");
488 logger
.info("Exported " + (count
- pastCount
) + " names. Total: " + count
);
492 txStatus
= startTransaction(true);
493 logger
.info("Started new transaction. Fetching some names first (max: " + limit
+ ") ...");
495 if (taxonNameList
.size() == 0) {
496 logger
.info("No names left to fetch.");
498 taxonNameList
= null;
499 // Commit transaction
500 commitTransaction(txStatus
);
501 logger
.debug("Committed transaction.");
507 * @param noteCategoryFk
508 * @param noteCategoryCache
512 private void invokeNotes(String note
, Integer noteCategoryFk
,
513 String noteCategoryCache
, Integer languageFk
, String languageCache
,
514 Integer taxonFk
, Connection connection
) {
515 String notesSql
= "UPDATE Note SET Note_1 = ?, NoteCategoryFk = ?, NoteCategoryCache = ?, LanguageFk = ?, LanguageCache = ? WHERE TaxonFk = ?";
517 PreparedStatement notesStmt
= connection
.prepareStatement(notesSql
);
520 notesStmt
.setString(1, note
);
522 notesStmt
.setObject(1, null);
525 if (noteCategoryFk
!= null) {
526 notesStmt
.setInt(2, noteCategoryFk
);
528 notesStmt
.setObject(2, null);
531 if (noteCategoryCache
!= null) {
532 notesStmt
.setString(3, noteCategoryCache
);
534 notesStmt
.setObject(3, null);
537 if (languageFk
!= null) {
538 notesStmt
.setInt(4, languageFk
);
540 notesStmt
.setObject(4, null);
543 if (languageCache
!= null) {
544 notesStmt
.setString(5, languageCache
);
546 notesStmt
.setObject(5, null);
549 if (taxonFk
!= null) {
550 notesStmt
.setInt(6, taxonFk
);
552 notesStmt
.setObject(6, null);
555 notesStmt
.executeUpdate();
556 } catch (SQLException e
) {
557 logger
.error("Note could not be created: " + note
);
565 * Deletes all entries of database tables related to <code>Note</code>.
566 * @param state The PesiExportState
567 * @return Whether the delete operation was successful or not.
569 protected boolean doDelete(PesiExportState state
) {
570 PesiExportConfigurator pesiConfig
= (PesiExportConfigurator
) state
.getConfig();
573 Source destination
= pesiConfig
.getDestination();
576 sql
= "DELETE FROM NoteSource";
577 destination
.setQuery(sql
);
578 destination
.update(sql
);
581 sql
= "DELETE FROM " + dbNoteTableName
;
582 destination
.setQuery(sql
);
583 destination
.update(sql
);
588 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IoStateBase)
591 protected boolean isIgnore(PesiExportState state
) {
592 return ! state
.getConfig().isDoDescription();
597 * Returns the <code>Note_2</code> attribute.
598 * @param descriptionElement The {@link DescriptionElementBase DescriptionElement}.
599 * @return The <code>Note_2</code> attribute.
602 @SuppressWarnings("unused")
603 private static String
getNote_2(DescriptionElementBase descriptionElement
) {
604 logger
.warn("Not yet implemented");
609 * Returns the <code>NoteCategoryFk</code> attribute.
610 * @param descriptionElement The {@link DescriptionElementBase DescriptionElement}.
611 * @return The <code>NoteCategoryFk</code> attribute.
614 private static Integer
getNoteCategoryFk(DescriptionElementBase descriptionElement
) {
615 Integer result
= null;
616 result
= PesiTransformer
.feature2NoteCategoryFk(descriptionElement
.getFeature());
621 * Returns the <code>NoteCategoryCache</code> attribute.
622 * @param descriptionElement The {@link DescriptionElementBase DescriptionElement}.
623 * @return The <code>NoteCategoryCache</code> attribute.
626 @SuppressWarnings("unused")
627 private static String
getNoteCategoryCache(DescriptionElementBase descriptionElement
, PesiExportState state
) {
628 return state
.getTransformer().getCacheByFeature(descriptionElement
.getFeature());
635 * Returns the <code>LanguageFk</code> attribute.
636 * @param descriptionElement The {@link DescriptionElementBase DescriptionElement}.
637 * @return The <code>LanguageFk</code> attribute.
640 @SuppressWarnings("unused")
641 private static Integer
getLanguageFk(DescriptionElementBase descriptionElement
) {
642 Language language
= getLanguage(descriptionElement
);
644 return PesiTransformer
.language2LanguageId(language
);
648 * Returns the <code>LanguageCache</code> attribute.
649 * @param descriptionElement The {@link DescriptionElementBase DescriptionElement}.
650 * @return The <code>LanguageCache</code> attribute.
651 * @throws UndefinedTransformerMethodException
654 @SuppressWarnings("unused")
655 private static String
getLanguageCache(DescriptionElementBase descriptionElement
, PesiExportState state
) throws UndefinedTransformerMethodException
{
656 Language language
= getLanguage(descriptionElement
);
657 return state
.getTransformer().getCacheByLanguage(language
);
660 private static Language
getLanguage(DescriptionElementBase descriptionElement
) {
661 Language language
= null;
663 Map
<Language
, LanguageString
> multilanguageText
= null;
664 if (descriptionElement
.isInstanceOf(CommonTaxonName
.class)) {
665 CommonTaxonName commonTaxonName
= CdmBase
.deproxy(descriptionElement
, CommonTaxonName
.class);
666 language
= commonTaxonName
.getLanguage();
667 } else if (descriptionElement
.isInstanceOf(TextData
.class)) {
668 TextData textData
= CdmBase
.deproxy(descriptionElement
, TextData
.class);
669 multilanguageText
= textData
.getMultilanguageText();
670 } else if (descriptionElement
.isInstanceOf(IndividualsAssociation
.class)) {
671 IndividualsAssociation individualsAssociation
= CdmBase
.deproxy(descriptionElement
, IndividualsAssociation
.class);
672 multilanguageText
= individualsAssociation
.getDescription();
673 } else if (descriptionElement
.isInstanceOf(TaxonInteraction
.class)) {
674 TaxonInteraction taxonInteraction
= CdmBase
.deproxy(descriptionElement
, TaxonInteraction
.class);
675 multilanguageText
= taxonInteraction
.getDescriptions();
677 logger
.debug("Given descriptionElement does not support languages. Hence LanguageCache could not be determined: " + descriptionElement
.getUuid());
680 if (multilanguageText
!= null) {
681 Set
<Language
> languages
= multilanguageText
.keySet();
683 // TODO: Think of something more sophisticated than this
684 if (languages
.size() > 0) {
685 language
= languages
.iterator().next();
687 if (languages
.size() > 1){
688 logger
.warn("There is more than 1 language for a given description (" + descriptionElement
.getClass().getSimpleName() + "):" + descriptionElement
.getUuid());
695 // * Returns the <code>Region</code> attribute.
696 // * @param descriptionElement The {@link DescriptionElementBase DescriptionElement}.
697 // * @return The <code>Region</code> attribute.
698 // * @see MethodMapper
700 // @SuppressWarnings("unused")
701 // private static String getRegion(DescriptionElementBase descriptionElement) {
702 // String result = null;
703 // DescriptionBase<?> inDescription = descriptionElement.getInDescription();
705 // // Area information are associated to TaxonDescriptions and Distributions.
706 // if (descriptionElement.isInstanceOf(Distribution.class)) {
707 // Distribution distribution = CdmBase.deproxy(descriptionElement, Distribution.class);
708 // result = PesiTransformer.area2AreaCache(distribution.getArea());
709 // } else if (inDescription != null && inDescription.isInstanceOf(TaxonDescription.class)) {
710 // TaxonDescription taxonDescription = CdmBase.deproxy(inDescription, TaxonDescription.class);
711 // Set<NamedArea> namedAreas = taxonDescription.getGeoScopes();
712 // if (namedAreas.size() == 1) {
713 // result = PesiTransformer.area2AreaCache(namedAreas.iterator().next());
714 // } else if (namedAreas.size() > 1) {
715 // logger.warn("This TaxonDescription contains more than one NamedArea: " + taxonDescription.getTitleCache());
723 * Returns the TaxonFk for a given TaxonName or Taxon.
724 * @param state The {@link DbExportStateBase DbExportState}.
727 @SuppressWarnings("unused") //used by mapper
728 private static Integer
getTaxonFk(DescriptionElementBase deb
, PesiExportState state
) {
729 IdentifiableEntity
<?
> entity
= state
.getCurrentTaxon();
730 return state
.getDbId(entity
);
734 * Returns the TaxonFk for a given TaxonName.
735 * @param taxonName The {@link TaxonNameBase TaxonName}.
736 * @param state The {@link DbExportStateBase DbExportState}.
739 private static Integer
getTaxonKey(TaxonNameBase
<?
,?
> taxonName
, DbExportStateBase
<?
, PesiTransformer
> state
) {
740 return state
.getDbId(taxonName
);
744 * Returns the <code>FullName</code> attribute.
745 * @param taxonName The {@link NonViralName NonViralName}.
746 * @return The <code>FullName</code> attribute.
749 @SuppressWarnings("unused")
750 private static String
getTaxonFullNameCache(DescriptionElementBase deb
, PesiExportState state
) {
752 IdentifiableEntity
<?
> taxon
= state
.getCurrentTaxon();
753 TaxonBase
<?
> taxonDeproxy
= CdmBase
.deproxy(taxon
, TaxonBase
.class);
754 TaxonNameBase
<?
,?
> taxonName
= taxonDeproxy
.getName();
756 NonViralName
<?
> nvn
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
757 String result
= getCacheStrategy(nvn
).getTitleCache(nvn
);
764 * Returns the CDM to PESI specific export mappings for PESI notes.
765 * @return The {@link PesiExportMapping PesiExportMapping}.
767 private PesiExportMapping
getNotesMapping() {
768 PesiExportMapping mapping
= new PesiExportMapping(dbNoteTableName
);
770 mapping
.addMapper(IdMapper
.NewInstance("NoteId"));
771 mapping
.addMapper(DbTextDataMapper
.NewInstance(Language
.ENGLISH(), "Note_1"));
773 mapping
.addMapper(DbExportNotYetImplementedMapper
.NewInstance("Note_2", "Need to research what Note_2 is for"));
774 mapping
.addMapper(MethodMapper
.NewInstance("NoteCategoryFk", this, DescriptionElementBase
.class ));
776 mapping
.addMapper(MethodMapper
.NewInstance("NoteCategoryCache", this, DescriptionElementBase
.class, PesiExportState
.class ));
777 mapping
.addMapper(MethodMapper
.NewInstance("LanguageFk", this));
778 mapping
.addMapper(MethodMapper
.NewInstance("LanguageCache", this, DescriptionElementBase
.class, PesiExportState
.class));
780 // mapping.addMapper(MethodMapper.NewInstance("Region", this));
781 mapping
.addMapper(DbDescriptionElementTaxonMapper
.NewInstance("taxonFk"));
782 mapping
.addMapper(ExpertsAndLastActionMapper
.NewInstance());
783 mapping
.addCollectionMapping(getNoteSourceMapping());
787 private CollectionExportMapping
<PesiExportState
, PesiExportConfigurator
,PesiTransformer
> getNoteSourceMapping() {
788 String tableName
= "NoteSource";
789 String collectionAttribute
= "sources";
790 IdMapper parentMapper
= IdMapper
.NewInstance("NoteFk");
791 CollectionExportMapping
<PesiExportState
, PesiExportConfigurator
, PesiTransformer
> mapping
= CollectionExportMapping
.NewInstance(tableName
, collectionAttribute
, parentMapper
);
792 mapping
.addMapper(DbSimpleFilterMapper
.NewSingleNullAttributeInstance("idInSource", "Sources with idInSource currently handle data lineage"));
793 mapping
.addMapper(DbObjectMapper
.NewInstance("Citation", "SourceFk"));
794 mapping
.addMapper(DbObjectMapper
.NewInstance("Citation", "SourceNameCache", IS_CACHE
));
795 mapping
.addMapper(DbStringMapper
.NewInstance("CitationMicroReference", "SourceDetail"));
801 * Returns the CDM to PESI specific export mappings for occurrences.
802 * @return The {@link PesiExportMapping PesiExportMapping}.
804 private PesiExportMapping
getOccurrenceMapping() {
805 PesiExportMapping mapping
= new PesiExportMapping(dbOccurrenceTableName
);
807 mapping
.addMapper(IdMapper
.NewInstance("OccurrenceId"));
808 mapping
.addMapper(DbDescriptionElementTaxonMapper
.NewInstance("taxonFk"));
809 mapping
.addMapper(DbDescriptionElementTaxonMapper
.NewInstance("TaxonFullNameCache", true, true, null));
811 mapping
.addMapper(DbAreaMapper
.NewInstance(Distribution
.class, "Area", "AreaFk", ! IS_CACHE
));
812 mapping
.addMapper(DbAreaMapper
.NewInstance(Distribution
.class, "Area", "AreaNameCache", IS_CACHE
));
813 mapping
.addMapper(DbDistributionStatusMapper
.NewInstance("OccurrenceStatusFk", ! IS_CACHE
));
814 mapping
.addMapper(DbDistributionStatusMapper
.NewInstance("OccurrenceStatusCache", IS_CACHE
));
816 // Use Occurrence source instead
817 mapping
.addMapper(DbExportIgnoreMapper
.NewInstance("SourceFk", "Use OccurrenceSource table for sources instead"));
818 mapping
.addMapper(DbExportIgnoreMapper
.NewInstance("SourceNameCache", "Use OccurrenceSource table for sources instead"));
821 mapping
.addMapper(DbExportNotYetImplementedMapper
.NewInstance("Notes", "Needs reimplementation in description export"));
822 mapping
.addMapper(ExpertsAndLastActionMapper
.NewInstance());
823 mapping
.addCollectionMapping(getOccurrenceSourceMapping());
828 private CollectionExportMapping
<PesiExportState
, PesiExportConfigurator
, PesiTransformer
> getOccurrenceSourceMapping() {
829 String tableName
= "OccurrenceSource";
830 String collectionAttribute
= "sources";
831 IdMapper parentMapper
= IdMapper
.NewInstance("OccurrenceFk");
832 CollectionExportMapping
<PesiExportState
, PesiExportConfigurator
, PesiTransformer
> mapping
= CollectionExportMapping
.NewInstance(tableName
, collectionAttribute
, parentMapper
);
833 mapping
.addMapper(DbSimpleFilterMapper
.NewSingleNullAttributeInstance("idInSource", "Sources with idInSource currently handle data lineage"));
834 mapping
.addMapper(DbObjectMapper
.NewInstance("Citation", "SourceFk"));
835 mapping
.addMapper(DbObjectMapper
.NewInstance("Citation", "SourceNameCache", IS_CACHE
));
836 mapping
.addMapper(DbOriginalNameMapper
.NewInstance("OldTaxonName", IS_CACHE
, null));
842 * Returns the CDM to PESI specific export mappings for additional taxon sources.
843 * @return The {@link PesiExportMapping PesiExportMapping}.
845 private PesiExportMapping
getAdditionalTaxonSourceMapping() {
846 PesiExportMapping mapping
= new PesiExportMapping(dbAdditionalSourceTableName
);
848 mapping
.addMapper(MethodMapper
.NewInstance("TaxonFk", this, DescriptionElementBase
.class, PesiExportState
.class));
851 mapping
.addMapper(DbSingleSourceMapper
.NewInstance("SourceFk", of (DbSingleSourceMapper
.EXCLUDE
.WITH_ID
) , ! IS_CACHE
));
852 mapping
.addMapper(DbSingleSourceMapper
.NewInstance("SourceNameCache", of(DbSingleSourceMapper
.EXCLUDE
.WITH_ID
) , ! IS_CACHE
));
854 // mapping.addMapper(MethodMapper.NewInstance("SourceUseFk", this));
855 // mapping.addMapper(MethodMapper.NewInstance("SourceUseCache", this));
856 // mapping.addMapper(MethodMapper.NewInstance("SourceFk", this.getClass(), "getSourceFk", standardMethodParameter, PesiExportState.class));
857 // mapping.addMapper(MethodMapper.NewInstance("SourceNameCache", this));
858 // mapping.addMapper(MethodMapper.NewInstance("SourceDetail", this));
864 * Returns the CDM to PESI specific export mappings for common names.
865 * @return The {@link PesiExportMapping PesiExportMapping}.
867 private PesiExportMapping
getVernacularNamesMapping() {
868 PesiExportMapping mapping
= new PesiExportMapping(dbVernacularTableName
);
870 mapping
.addMapper(IdMapper
.NewInstance("CommonNameId"));
871 mapping
.addMapper(DbDescriptionElementTaxonMapper
.NewInstance("taxonFk"));
873 mapping
.addMapper(DbStringMapper
.NewInstance("Name", "CommonName"));
874 mapping
.addMapper(DbAreaMapper
.NewInstance(CommonTaxonName
.class, "Area", "Region", IS_CACHE
));
876 mapping
.addMapper(DbLanguageMapper
.NewInstance(CommonTaxonName
.class, "Language", "LanguageFk", ! IS_CACHE
));
877 mapping
.addMapper(DbLanguageMapper
.NewInstance(CommonTaxonName
.class, "Language", "LanguageCache", IS_CACHE
));
879 mapping
.addMapper(DbSingleSourceMapper
.NewInstance("SourceFk", of ( DbSingleSourceMapper
.EXCLUDE
.WITH_ID
) , ! IS_CACHE
));
880 mapping
.addMapper(DbSingleSourceMapper
.NewInstance("SourceNameCache", of ( DbSingleSourceMapper
.EXCLUDE
.WITH_ID
) , IS_CACHE
));
881 mapping
.addMapper(ExpertsAndLastActionMapper
.NewInstance());
886 private PesiExportMapping
getImageMapping() {
887 PesiExportMapping mapping
= new PesiExportMapping(dbImageTableName
);
888 mapping
.addMapper(DbDescriptionElementTaxonMapper
.NewInstance("taxonFk"));