View Javadoc

1   // $Id$
2   /**
3   * Copyright (C) 2009 EDIT
4   * European Distributed Institute of Taxonomy 
5   * http://www.e-taxonomy.eu
6   * 
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.
9   */
10  package eu.etaxonomy.cdm.io.pesi.out;
11  
12  import java.sql.SQLException;
13  import java.util.List;
14  import java.util.Set;
15  
16  import org.apache.log4j.Logger;
17  import org.springframework.stereotype.Component;
18  import org.springframework.transaction.TransactionStatus;
19  
20  import eu.etaxonomy.cdm.io.berlinModel.out.mapper.MethodMapper;
21  import eu.etaxonomy.cdm.io.common.Source;
22  import eu.etaxonomy.cdm.model.common.CdmBase;
23  import eu.etaxonomy.cdm.model.common.DescriptionElementSource;
24  import eu.etaxonomy.cdm.model.description.DescriptionBase;
25  import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
26  import eu.etaxonomy.cdm.model.description.TaxonDescription;
27  import eu.etaxonomy.cdm.model.description.TextData;
28  import eu.etaxonomy.cdm.model.name.TaxonNameBase;
29  import eu.etaxonomy.cdm.model.reference.ReferenceBase;
30  import eu.etaxonomy.cdm.model.taxon.Taxon;
31  import eu.etaxonomy.cdm.model.taxon.TaxonBase;
32  
33  /**
34   * The export class for additional information linked to {@link eu.etaxonomy.cdm.model.taxon.Taxon Taxa} and {@link eu.etaxonomy.cdm.model.reference.ReferenceBase References}.<p>
35   * Inserts into DataWarehouse database table <code>AdditionalTaxonSource</code>.
36   * @author e.-m.lee
37   * @date 23.02.2010
38   *
39   */
40  @Component
41  @SuppressWarnings("unchecked")
42  public class PesiAdditionalTaxonSourceExport extends PesiExportBase {
43  	private static final Logger logger = Logger.getLogger(PesiAdditionalTaxonSourceExport.class);
44  	private static final Class<? extends CdmBase> standardMethodParameter = ReferenceBase.class;
45  
46  	private static int modCount = 1000;
47  	private static final String dbTableName = "AdditionalTaxonSource";
48  	private static final String pluralString = "DescriptionElements";
49  	private static final String parentPluralString = "Taxa";
50  	private static boolean sourceUse_AdditionalSource = false;
51  	private static boolean sourceUse_NomenclaturalReference = false;
52  	private static boolean sourceUse_SourceOfSynonymy = false;
53  	private static TaxonNameBase currentTaxonName = null;
54  	private static String citationMicroReference = null;
55  	
56  	public PesiAdditionalTaxonSourceExport() {
57  		super();
58  	}
59  
60  	/* (non-Javadoc)
61  	 * @see eu.etaxonomy.cdm.io.common.DbExportBase#getStandardMethodParameter()
62  	 */
63  	@Override
64  	public Class<? extends CdmBase> getStandardMethodParameter() {
65  		return standardMethodParameter;
66  	}
67  
68  	/* (non-Javadoc)
69  	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IoStateBase)
70  	 */
71  	@Override
72  	protected boolean doCheck(PesiExportState state) {
73  		boolean result = true;
74  		return result;
75  	}
76  
77  	/* (non-Javadoc)
78  	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doInvoke(eu.etaxonomy.cdm.io.common.IoStateBase)
79  	 */
80  	@Override
81  	protected boolean doInvoke(PesiExportState state) {
82  		try {
83  			logger.error("*** Started Making " + pluralString + " ...");
84  
85  			// Get the limit for objects to save within a single transaction.
86  //			int limit = state.getConfig().getLimitSave();
87  			int limit = 1000;
88  
89  			// Stores whether this invoke was successful or not.
90  			boolean success = true;
91  	
92  			// PESI: Clear the database table Note.
93  			doDelete(state);
94  	
95  			// CDM: Get the number of all available description elements.
96  //			int maxCount = getDescriptionService().count(null);
97  //			logger.error("Total amount of " + maxCount + " " + pluralString + " will be exported.");
98  
99  			// Get specific mappings: (CDM) DescriptionElement -> (PESI) Note
100 			PesiExportMapping mapping = getMapping();
101 	
102 			// Initialize the db mapper
103 			mapping.initialize(state);
104 	
105 			// PESI: Create the Notes
106 			int count = 0;
107 			int taxonCount = 0;
108 			int pastCount = 0;
109 			TransactionStatus txStatus = null;
110 			List<TaxonBase> list = null;
111 
112 			// Start transaction
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 				
120 				logger.error("PHASE 2: Check for SourceUse 'Additional Source'");
121 				sourceUse_AdditionalSource = true;
122 				for (TaxonBase taxonBase : list) {
123 					
124 					// Set the current Taxon
125 					currentTaxonName = taxonBase.getName();
126 
127 					if (taxonBase.isInstanceOf(Taxon.class)) {
128 						
129 						Taxon taxon = CdmBase.deproxy(taxonBase, Taxon.class);
130 
131 						// Determine the TaxonDescriptions
132 						Set<TaxonDescription> taxonDescriptions = taxon.getDescriptions();
133 
134 						// Determine the DescriptionElements (Citations) for the current Taxon
135 						for (TaxonDescription taxonDescription : taxonDescriptions) {
136 							Set<DescriptionElementBase> descriptionElements = taxonDescription.getElements();
137 							
138 							for (DescriptionElementBase descriptionElement : descriptionElements) {
139 								// According to FaEu Import those DescriptionElementBase elements are of instance TextData
140 								// There are no other indicators
141 								if (descriptionElement.isInstanceOf(TextData.class)) {
142 									Set<DescriptionElementSource> elementSources = descriptionElement.getSources();
143 									
144 									for (DescriptionElementSource elementSource : elementSources) {
145 										
146 										// Set the CitationMicroReference so it is accessible later in getSourceDetail()
147 										setCitationMicroReference(elementSource.getCitationMicroReference());
148 	
149 										// Get the citation
150 										ReferenceBase reference = elementSource.getCitation();
151 										
152 										// Check whether it was a synonym originally
153 										TaxonNameBase nameUsedInSource = elementSource.getNameUsedInSource();
154 										if (nameUsedInSource != null) {
155 											// It was a synonym originally: Set currentTaxonName to synonym's taxonName
156 											currentTaxonName = nameUsedInSource;
157 										}
158 										
159 										// Citations can be empty (null): Is it wrong data or just a normal case?
160 										if (reference != null) {
161 											if (neededValuesNotNull(reference, state)) {
162 												doCount(count++, modCount, pluralString);
163 												success &= mapping.invoke(reference);
164 											}
165 										}
166 									}
167 								}
168 							}
169 						}
170 					}
171 					
172 				}
173 				sourceUse_AdditionalSource = false;
174 				logger.error("Exported " + (count - pastCount) + " " + pluralString + ".");
175 				
176 				// Commit transaction
177 				commitTransaction(txStatus);
178 				logger.error("Committed transaction.");
179 				logger.error("Exported " + (count - pastCount) + " " + pluralString + ". Total: " + count);
180 				pastCount = count;
181 
182 				// Start transaction
183 				txStatus = startTransaction(true);
184 				logger.error("Started new transaction. Fetching some " + parentPluralString + " first (max: " + limit + ") ...");
185 			}
186 			if (list.size() == 0) {
187 				logger.error("No " + pluralString + " left to fetch.");
188 			}
189 			// Commit transaction
190 			commitTransaction(txStatus);
191 			logger.error("Committed transaction.");
192 	
193 			logger.error("*** Finished Making " + pluralString + " ..." + getSuccessString(success));
194 			
195 			return success;
196 		} catch (SQLException e) {
197 			e.printStackTrace();
198 			logger.error(e.getMessage());
199 			return false;
200 		}
201 	}
202 
203 	/**
204 	 * Checks whether needed values for an entity are NULL.
205 	 * @return
206 	 */
207 	private boolean neededValuesNotNull(ReferenceBase<?> reference, PesiExportState state) {
208 		boolean result = true;
209 		if (getSourceFk(reference, state) == null) {
210 			logger.error("SourceFk is NULL, but is not allowed to be. Therefore no record was written to export database for this reference: " + reference.getUuid());
211 			result = false;
212 		}
213 		if (getSourceUseFk(reference) == null) {
214 			logger.error("SourceUseFk is NULL, but is not allowed to be. Therefore no record was written to export database for this reference: " + reference.getUuid());
215 			result = false;
216 		}
217 		return result;
218 	}
219 	
220 	/**
221 	 * Deletes all entries of database tables related to <code>AdditionalTaxonSource</code>.
222 	 * @param state The {@link PesiExportState PesiExportState}.
223 	 * @return Whether the delete operation was successful or not.
224 	 */
225 	protected boolean doDelete(PesiExportState state) {
226 		PesiExportConfigurator pesiConfig = (PesiExportConfigurator) state.getConfig();
227 		
228 		String sql;
229 		Source destination =  pesiConfig.getDestination();
230 
231 		// Clear AdditionalTaxonSource
232 		sql = "DELETE FROM " + dbTableName;
233 		destination.setQuery(sql);
234 		destination.update(sql);
235 		return true;
236 	}
237 
238 	/* (non-Javadoc)
239 	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IoStateBase)
240 	 */
241 	@Override
242 	protected boolean isIgnore(PesiExportState state) {
243 		// TODO
244 //		return state.getConfig().isDoAdditionalTaxonSource()
245 		return false;
246 	}
247 
248 	/**
249 	 * Returns the <code>TaxonFk</code> attribute.
250 	 * @param reference The {@link ReferenceBase Reference}.
251 	 * @see MethodMapper
252 	 */
253 	@SuppressWarnings("unused")
254 	private static Integer getTaxonFk(ReferenceBase<?> reference, PesiExportState state) {
255 		// ReferenceBase parameter isn't needed, but the DbSingleAttributeExportMapperBase throws a type mismatch exception otherwise
256 		// since it awaits two parameters if one of them is of instance DbExportStateBase.
257 		Integer result = null;
258 		if (state != null && currentTaxonName != null) {
259 			result = state.getDbId(currentTaxonName);
260 		}
261 		return result;
262 	}
263 	
264 	/**
265 	 * Returns the <code>SourceFk</code> attribute.
266 	 * @param reference The {@link ReferenceBase Reference}.
267 	 * @return The <code>SourceFk</code> attribute.
268 	 * @see MethodMapper
269 	 */
270 	private static Integer getSourceFk(ReferenceBase<?> reference, PesiExportState state) {
271 		Integer result = null;
272 		if (state != null && reference != null) {
273 			result = state.getDbId(reference);
274 		}
275 		return result;
276 	}
277 	
278 	/**
279 	 * Returns the <code>SourceUseFk</code> attribute.
280 	 * @param reference The {@link ReferenceBase Reference}.
281 	 * @return The <code>SourceUseFk</code> attribute.
282 	 * @see MethodMapper
283 	 */
284 	private static Integer getSourceUseFk(ReferenceBase<?> reference) {
285 		// TODO
286 		Integer result = null;
287 		if (sourceUse_AdditionalSource) {
288 			result = PesiTransformer.sourceUseIdSourceUseId(3);
289 		} else if (sourceUse_SourceOfSynonymy) {
290 			result = PesiTransformer.sourceUseIdSourceUseId(4);
291 		} else if (sourceUse_NomenclaturalReference) {
292 			result = PesiTransformer.sourceUseIdSourceUseId(8);
293 		}
294 		return result;
295 	}
296 	
297 	/**
298 	 * Returns the <code>SourceUseCache</code> attribute.
299 	 * @param reference The {@link ReferenceBase Reference}.
300 	 * @return The <code>SourceUseCache</code> attribute.
301 	 * @see MethodMapper
302 	 */
303 	@SuppressWarnings("unused")
304 	private static String getSourceUseCache(ReferenceBase<?> reference) {
305 		// TODO
306 		String result = null;
307 		if (sourceUse_AdditionalSource) {
308 			result = PesiTransformer.sourceUseId2SourceUseCache(3);
309 		} else if (sourceUse_SourceOfSynonymy) {
310 			result = PesiTransformer.sourceUseId2SourceUseCache(4);
311 		} else if (sourceUse_NomenclaturalReference) {
312 			result = PesiTransformer.sourceUseId2SourceUseCache(8);
313 		}
314 		return result;
315 	}
316 	
317 	/**
318 	 * Returns the <code>SourceNameCache</code> attribute.
319 	 * @param reference The {@link ReferenceBase Reference}.
320 	 * @return The <code>SourceNameCache</code> attribute.
321 	 * @see MethodMapper
322 	 */
323 	@SuppressWarnings("unused")
324 	private static String getSourceNameCache(ReferenceBase<?> reference) {
325 		String result = null;
326 		if (reference != null) {
327 			result = reference.getTitle();
328 		}
329 		return result;
330 	}
331 	
332 	/**
333 	 * Returns the <code>SourceDetail</code> attribute.
334 	 * @param reference The {@link ReferenceBase Reference}.
335 	 * @return The <code>SourceDetail</code> attribute.
336 	 * @see MethodMapper
337 	 */
338 	@SuppressWarnings("unused")
339 	private static String getSourceDetail(ReferenceBase<?> reference) {
340 		return PesiAdditionalTaxonSourceExport.citationMicroReference;
341 	}
342 
343 	/**
344 	 * @param citationMicroReference the citationMicroReference to set
345 	 */
346 	public static void setCitationMicroReference(String citationMicroReference) {
347 		PesiAdditionalTaxonSourceExport.citationMicroReference = citationMicroReference;
348 	}
349 
350 	/**
351 	 * Returns the CDM to PESI specific export mappings.
352 	 * @return The {@link PesiExportMapping PesiExportMapping}.
353 	 */
354 	private PesiExportMapping getMapping() {
355 		PesiExportMapping mapping = new PesiExportMapping(dbTableName);
356 		
357 		mapping.addMapper(MethodMapper.NewInstance("TaxonFk", this.getClass(), "getTaxonFk", standardMethodParameter, PesiExportState.class));
358 		mapping.addMapper(MethodMapper.NewInstance("SourceFk", this.getClass(), "getSourceFk", standardMethodParameter, PesiExportState.class));
359 		mapping.addMapper(MethodMapper.NewInstance("SourceUseFk", this));
360 		mapping.addMapper(MethodMapper.NewInstance("SourceUseCache", this));
361 		mapping.addMapper(MethodMapper.NewInstance("SourceNameCache", this));
362 		mapping.addMapper(MethodMapper.NewInstance("SourceDetail", this));
363 		
364 		return mapping;
365 	}
366 
367 }