1
2
3
4
5
6
7
8
9
10 package eu.etaxonomy.cdm.io.pesi.out;
11
12 import java.sql.Connection;
13 import java.sql.PreparedStatement;
14 import java.sql.SQLException;
15 import java.util.HashMap;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Set;
19
20 import org.apache.log4j.Logger;
21 import org.springframework.stereotype.Component;
22 import org.springframework.transaction.TransactionStatus;
23
24 import eu.etaxonomy.cdm.io.berlinModel.out.mapper.MethodMapper;
25 import eu.etaxonomy.cdm.io.common.DbExportStateBase;
26 import eu.etaxonomy.cdm.io.common.Source;
27 import eu.etaxonomy.cdm.model.common.AnnotatableEntity;
28 import eu.etaxonomy.cdm.model.common.CdmBase;
29 import eu.etaxonomy.cdm.model.common.DescriptionElementSource;
30 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
31 import eu.etaxonomy.cdm.model.description.Distribution;
32 import eu.etaxonomy.cdm.model.description.TaxonDescription;
33 import eu.etaxonomy.cdm.model.location.NamedArea;
34 import eu.etaxonomy.cdm.model.reference.ReferenceBase;
35 import eu.etaxonomy.cdm.model.taxon.Taxon;
36 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
37 import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
38
39
40
41
42
43
44
45
46 @Component
47 @SuppressWarnings("unchecked")
48 public class PesiOccurrenceExport extends PesiExportBase {
49 private static final Logger logger = Logger.getLogger(PesiOccurrenceExport.class);
50 private static final Class<? extends CdmBase> standardMethodParameter = AnnotatableEntity.class;
51
52 private static int modCount = 1000;
53 private static final String dbTableName = "Occurrence";
54 private static final String pluralString = "Occurrences";
55 private static final String parentPluralString = "Taxa";
56 private static Taxon taxon = null;
57 private static Map<Integer, Integer> sourceId2OccurenceIdMap = new HashMap<Integer, Integer>();
58 private static NamedArea namedArea = null;
59 private static Distribution distribution = null;
60
61 public PesiOccurrenceExport() {
62 super();
63 }
64
65
66
67
68 @Override
69 public Class<? extends CdmBase> getStandardMethodParameter() {
70 return standardMethodParameter;
71 }
72
73
74
75
76 @Override
77 protected boolean doCheck(PesiExportState state) {
78 boolean result = true;
79 return result;
80 }
81
82
83
84
85 @Override
86 protected boolean doInvoke(PesiExportState state) {
87 try {
88 logger.error("*** Started Making " + pluralString + " ...");
89
90
91 int limit = state.getConfig().getLimitSave();
92
93
94 boolean success = true;
95
96
97
98
99
100 PesiExportMapping mapping = getMapping();
101
102
103 mapping.initialize(state);
104
105
106 int count = 0;
107 int taxonCount = 0;
108 int pastCount = 0;
109 TransactionStatus txStatus = null;
110 List<TaxonBase> list = null;
111
112
113 txStatus = startTransaction(true);
114 logger.error("Started new transaction. Fetching some " + parentPluralString + " first (max: " + limit + ") ...");
115 while ((list = getTaxonService().list(null, limit, taxonCount, null, null)).size() > 0) {
116
117 taxonCount += list.size();
118 logger.error("Fetched " + list.size() + " " + parentPluralString + ".");
119 for (TaxonBase taxonBase : list) {
120 if (taxonBase.isInstanceOf(Taxon.class)) {
121
122
123 taxon = CdmBase.deproxy(taxonBase, Taxon.class);
124
125
126 Set<TaxonDescription> taxonDescriptions = taxon.getDescriptions();
127
128
129 for (TaxonDescription taxonDescription : taxonDescriptions) {
130 Set<DescriptionElementBase> descriptionElements = taxonDescription.getElements();
131 for (DescriptionElementBase descriptionElement : descriptionElements) {
132 Set<DescriptionElementSource> elementSources = descriptionElement.getSources();
133
134 if (descriptionElement.isInstanceOf(Distribution.class)) {
135 Distribution distribution = CdmBase.deproxy(descriptionElement, Distribution.class);
136 setNamedArea(distribution.getArea());
137 setDistribution(distribution);
138
139
140 if (elementSources.size() == 0 && state.getDbId(descriptionElement) != null) {
141 if (neededValuesNotNull(descriptionElement, state)) {
142 doCount(count++, modCount, pluralString);
143 success &= mapping.invoke(descriptionElement);
144 }
145 } else {
146 for (DescriptionElementSource elementSource : elementSources) {
147 ReferenceBase reference = elementSource.getCitation();
148
149
150 if (reference != null && state.getDbId(reference) != null) {
151 if (neededValuesNotNull(reference, state)) {
152 doCount(count++, modCount, pluralString);
153 success &= mapping.invoke(reference);
154 }
155 }
156 }
157
158 }
159
160 setDistribution(null);
161 }
162
163 }
164 }
165 }
166 }
167
168
169 commitTransaction(txStatus);
170 logger.error("Committed transaction.");
171 logger.error("Exported " + (count - pastCount) + " " + pluralString + ". Total: " + count);
172 pastCount = count;
173
174
175 txStatus = startTransaction(true);
176 logger.error("Started new transaction. Fetching some " + parentPluralString + " first (max: " + limit + ") ...");
177 }
178 if (list.size() == 0) {
179 logger.error("No " + parentPluralString + " left to fetch.");
180 }
181
182 commitTransaction(txStatus);
183 logger.error("Committed transaction.");
184
185 logger.error("*** Finished Making " + pluralString + " ..." + getSuccessString(success));
186
187 return success;
188 } catch (SQLException e) {
189 e.printStackTrace();
190 logger.error(e.getMessage());
191 return false;
192 }
193 }
194
195
196
197
198
199 private boolean neededValuesNotNull(AnnotatableEntity entity, PesiExportState state) {
200 boolean result = true;
201 if (getTaxonFk(entity, state) == null) {
202 logger.error("TaxonFk is NULL, but is not allowed to be. Therefore no record was written to export database for this entity: " + entity.getUuid());
203 result = false;
204 }
205 if (getAreaFk(entity) == null) {
206 logger.error("AreaFk is NULL, but is not allowed to be. Therefore no record was written to export database for this entity: " + entity.getUuid());
207 result = false;
208 }
209 if (getOccurrenceStatusFk(entity) == null) {
210 logger.error("OccurrenceStatusFk is NULL, but is not allowed to be. Therefore no record was written to export database for this entity: " + entity.getUuid());
211 result = false;
212 }
213 return result;
214 }
215
216
217
218
219
220
221
222 protected boolean invokeOccurrenceSource(AnnotatableEntity entity, PesiExportState state) {
223 if (entity == null) {
224 return true;
225 } else {
226
227 String lastStoredRecordSql = "Insert Into OccurrenceSource (OccurrenceFk, SourceFk, SourceNameCache, OldTaxonName) " +
228 "values(?, ?, ?, ?)";
229 Connection con = state.getConfig().getDestination().getConnection();
230
231 try {
232 PreparedStatement stmt = con.prepareStatement(lastStoredRecordSql);
233 Integer sourceFk = getSourceFk(entity, state);
234 stmt.setInt(1, sourceId2OccurenceIdMap.get(sourceFk));
235 stmt.setInt(2, sourceFk);
236 stmt.setString(3, getSourceCache(entity));
237 stmt.setString(4, null);
238 stmt.executeUpdate();
239 return true;
240 } catch (SQLException e) {
241 logger.error("SQLException during getOccurrenceId invoke...");
242 e.printStackTrace();
243 return false;
244 }
245 }
246 }
247
248
249
250
251
252
253 protected boolean doDelete(PesiExportState state) {
254 PesiExportConfigurator pesiConfig = (PesiExportConfigurator) state.getConfig();
255
256 String sql;
257 Source destination = pesiConfig.getDestination();
258
259
260 sql = "DELETE FROM " + dbTableName;
261 destination.setQuery(sql);
262 destination.update(sql);
263 return true;
264 }
265
266
267
268
269 @Override
270 protected boolean isIgnore(PesiExportState state) {
271 return ! state.getConfig().isDoOccurrence();
272 }
273
274
275
276
277
278
279
280
281 private static Integer getTaxonFk(AnnotatableEntity entity, PesiExportState state) {
282
283
284 Integer result = null;
285 if (state != null && taxon != null) {
286 result = state.getDbId(taxon.getName());
287 }
288 return result;
289 }
290
291
292
293
294
295
296
297 @SuppressWarnings("unused")
298 private static String getTaxonFullNameCache(AnnotatableEntity entity) {
299 String result = null;
300 result = taxon.getName().getTitleCache();
301 return result;
302 }
303
304
305
306
307
308
309
310 private static Integer getAreaFk(AnnotatableEntity entity) {
311 Integer result = null;
312 if (getNamedArea() != null) {
313 result = PesiTransformer.area2AreaId(namedArea);
314 } else {
315 logger.warn("This should never happen, but a NamedArea could not be found for entity: " + entity.getUuid());
316 }
317 return result;
318 }
319
320
321
322
323
324
325
326 @SuppressWarnings("unused")
327 private static String getAreaNameCache(AnnotatableEntity entity) {
328 String result = null;
329 if (getNamedArea() != null) {
330 result = PesiTransformer.area2AreaCache(namedArea);
331 } else {
332 logger.warn("This should never happen, but a NamedArea could not be found for entity: " + entity.getUuid());
333 }
334 return result;
335 }
336
337
338
339
340 public static Distribution getDistribution() {
341 return distribution;
342 }
343
344
345
346
347 public static void setDistribution(Distribution distribution) {
348 PesiOccurrenceExport.distribution = distribution;
349 }
350
351
352
353
354 public static NamedArea getNamedArea() {
355 return namedArea;
356 }
357
358
359
360
361 public static void setNamedArea(NamedArea namedArea) {
362 PesiOccurrenceExport.namedArea = namedArea;
363 }
364
365
366
367
368
369
370
371
372 private static Integer getOccurrenceStatusFk(AnnotatableEntity entity) {
373 Integer result = null;
374 if (getDistribution() != null) {
375 result = PesiTransformer.presenceAbsenceTerm2OccurrenceStatusId(getDistribution().getStatus());
376 }
377 return result;
378 }
379
380
381
382
383
384
385
386
387 @SuppressWarnings("unused")
388 private static String getOccurrenceStatusCache(AnnotatableEntity entity) {
389 String result = null;
390 if (getDistribution() != null) {
391 result = PesiTransformer.presenceAbsenceTerm2OccurrenceStatusCache(getDistribution().getStatus());
392 }
393 return result;
394 }
395
396
397
398
399
400
401
402
403 private static Integer getSourceFk(AnnotatableEntity entity, PesiExportState state) {
404 Integer result = null;
405 if (state != null && entity != null && entity.isInstanceOf(Distribution.class)) {
406 Distribution distribution = CdmBase.deproxy(entity, Distribution.class);
407 Set<DescriptionElementSource> sources = distribution.getSources();
408 if (sources.size() == 1) {
409 DescriptionElementSource source = sources.iterator().next();
410 result = state.getDbId(source.getCitation());
411 } else if (sources.size() > 1) {
412 logger.warn("Found Distribution with " + sources.size() + " sources.");
413 }
414 }
415 return result;
416 }
417
418
419
420
421
422
423
424 private static String getSourceCache(AnnotatableEntity entity) {
425 String result = null;
426 ReferenceBase reference;
427 if (entity != null && entity.isInstanceOf(Distribution.class)) {
428 Distribution distribution = CdmBase.deproxy(entity, Distribution.class);
429 Set<DescriptionElementSource> sources = distribution.getSources();
430 if (sources.size() == 1) {
431 DescriptionElementSource source = sources.iterator().next();
432 reference = source.getCitation();
433 if (reference != null) {
434 result = reference.getTitle();
435 }
436 } else if (sources.size() > 1) {
437 logger.warn("Found Distribution with " + sources.size() + " sources.");
438 }
439 }
440 return result;
441 }
442
443
444
445
446
447
448
449 @SuppressWarnings("unused")
450 private static String getNotes(AnnotatableEntity entity) {
451
452 return null;
453 }
454
455
456
457
458
459 private PesiExportMapping getMapping() {
460 PesiExportMapping mapping = new PesiExportMapping(dbTableName);
461
462 mapping.addMapper(MethodMapper.NewInstance("TaxonFk", this.getClass(), "getTaxonFk", standardMethodParameter, PesiExportState.class));
463 mapping.addMapper(MethodMapper.NewInstance("AreaFk", this));
464 mapping.addMapper(MethodMapper.NewInstance("TaxonFullNameCache", this));
465 mapping.addMapper(MethodMapper.NewInstance("AreaNameCache", this));
466 mapping.addMapper(MethodMapper.NewInstance("OccurrenceStatusFk", this));
467 mapping.addMapper(MethodMapper.NewInstance("OccurrenceStatusCache", this));
468 mapping.addMapper(MethodMapper.NewInstance("SourceFk", this.getClass(), "getSourceFk", standardMethodParameter, PesiExportState.class));
469 mapping.addMapper(MethodMapper.NewInstance("SourceCache", this));
470 mapping.addMapper(MethodMapper.NewInstance("Notes", this));
471
472 return mapping;
473 }
474
475 }