fix #6799: add totalCount of ticks as totalwork and start the progress monitor when...
[cdmlib.git] / cdmlib-io / src / main / java / eu / etaxonomy / cdm / io / common / CdmApplicationAwareDefaultExport.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.common;
11
12 import java.util.ArrayList;
13 import java.util.HashMap;
14 import java.util.List;
15 import java.util.Map;
16
17 import org.apache.log4j.Logger;
18 import org.springframework.beans.BeansException;
19 import org.springframework.context.ApplicationContext;
20 import org.springframework.context.ApplicationContextAware;
21 import org.springframework.stereotype.Component;
22
23 import eu.etaxonomy.cdm.api.service.IService;
24 import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
25 import eu.etaxonomy.cdm.common.monitor.SubProgressMonitor;
26 import eu.etaxonomy.cdm.io.common.events.IIoObserver;
27 import eu.etaxonomy.cdm.model.common.CdmBase;
28
29 /**
30 * This class is an default exporter class that is a spring bean and therefore it knows all other IO classes that are beans
31 *
32 * @author a.mueller
33 * @created 20.06.2008
34 */
35
36 @Component("defaultExport")
37 public class CdmApplicationAwareDefaultExport<T extends IExportConfigurator>
38 implements ICdmExporter<T>, ApplicationContextAware {
39
40 private static final Logger logger = Logger.getLogger(CdmApplicationAwareDefaultExport.class);
41
42 protected ApplicationContext applicationContext;
43
44 @Override
45 public void setApplicationContext(ApplicationContext applicationContext)
46 throws BeansException {
47 this.applicationContext = applicationContext;
48 }
49
50
51 //Constants
52 final static boolean OBLIGATORY = true;
53 final static boolean FACULTATIVE = false;
54 final int modCount = 1000;
55
56 private final IService service = null;
57
58 //different type of stores that are used by the known imports
59 Map<String, MapWrapper<? extends CdmBase>> stores = new HashMap<String, MapWrapper<? extends CdmBase>>();
60
61 public CdmApplicationAwareDefaultExport(){
62 stores.put(ICdmIO.TEAM_STORE, new MapWrapper<>(service));
63 stores.put(ICdmIO.REFERENCE_STORE, new MapWrapper<>(service));
64 stores.put(ICdmIO.NOMREF_STORE, new MapWrapper<>(service));
65 stores.put(ICdmIO.TAXONNAME_STORE, new MapWrapper<>(service));
66 stores.put(ICdmIO.TAXON_STORE, new MapWrapper<>(service));
67 stores.put(ICdmIO.SPECIMEN_STORE, new MapWrapper<>(service));
68 }
69
70
71 @Override
72 public ExportResult invoke(T config){
73 ExportResult result;
74 if (config.getCheck().equals(IExportConfigurator.CHECK.CHECK_ONLY)){
75 result = ExportResult.NewInstance(config.getResultType());
76 boolean success = doCheck(config);
77 if (! success){
78 result.setAborted();
79 }
80 }else if (config.getCheck().equals(IExportConfigurator.CHECK.CHECK_AND_EXPORT)){
81 boolean success = doCheck(config);
82 if (success){
83 result = doExport(config);
84 }else{
85 result = ExportResult.NewInstance(config.getResultType());
86 result.setAborted();
87 }
88 }else if (config.getCheck().equals(IExportConfigurator.CHECK.EXPORT_WITHOUT_CHECK)){
89 result = doExport(config);
90 }else{
91 result = ExportResult.NewInstance(config.getResultType());
92 String message = "Unknown CHECK type";
93 logger.error(message);
94 result.addError(message);
95 }
96 return result;
97 }
98
99
100 public ExportResult execute(T config) {
101 ExportResult result = ExportResult.NewInstance(config.getResultType());
102 if (config.getCheck().equals(IExportConfigurator.CHECK.CHECK_ONLY)){
103 boolean success = doCheck(config);
104 if (! success){
105 result.setAborted();
106 }
107 } else if (config.getCheck().equals(IExportConfigurator.CHECK.CHECK_AND_EXPORT)){
108 boolean success = doCheck(config);
109 if (success){
110 result = doExport(config);
111 }else{
112 result.setAborted();
113 }
114 } else if (config.getCheck().equals(IExportConfigurator.CHECK.EXPORT_WITHOUT_CHECK)){
115 result = doExport(config);
116 } else{
117 String message = "Unknown CHECK type";
118 logger.error(message);
119 result.addError(message);
120 }
121 return result;
122 }
123
124 @SuppressWarnings("unchecked")
125 protected <S extends IExportConfigurator> boolean doCheck(S config){
126
127 boolean result = true;
128
129 //check
130 if (config == null){
131 logger.warn("CdmExportConfiguration is null");
132 // result.setState(ExportResultState.ABORTED);
133 return false;
134 }else if (! config.isValid()){
135 logger.warn("CdmExportConfiguration is not valid");
136 // result.setState(ExportResultState.ABORTED);
137 return false;
138 }
139 System.out.println("Start checking Source ("+ config.getSourceNameString() + ") ...");
140
141 ExportStateBase state = config.getNewState();
142 state.initialize(config);
143
144 //do check for each class
145 for (Class<ICdmExport> ioClass: config.getIoClassList()){
146 try {
147 String ioBeanName = getComponentBeanName(ioClass);
148 ICdmIO cdmIo = applicationContext.getBean(ioBeanName, ICdmIO.class);
149 if (cdmIo != null){
150 registerObservers(config, cdmIo);
151 result &= cdmIo.check(state);
152 unRegisterObservers(config, cdmIo);
153 }else{
154 String message = "cdmIO for class " + (ioClass == null ? "(null)" : ioClass.getSimpleName()) + " was null";
155 logger.error(message);
156 return false;
157 }
158 } catch (Exception e) {
159 logger.error(e);
160 e.printStackTrace();
161 return false;
162 }
163 }
164
165 //return
166 System.out.println("End checking Source ("+ config.getSourceNameString() + ") for export from Cdm");
167 return result;
168
169 }
170
171
172 private void registerObservers(IExportConfigurator config, ICdmIO io){
173 for (IIoObserver observer : config.getObservers()){
174 io.addObserver(observer);
175 }
176 }
177
178 private void unRegisterObservers(IExportConfigurator config, ICdmIO io){
179 for (IIoObserver observer : config.getObservers()){
180 io.removeObserver(observer);
181 }
182 }
183
184
185
186 /**
187 * Executes the whole
188 */
189 protected <CONFIG extends T> ExportResult doExport(CONFIG config){
190 //validate
191 if (config == null){
192 ExportResult result = ExportResult.NewInstance(null);
193 String message = "Configuration is null";
194 logger.error(message);
195 result.addError(message);
196 result.setAborted();
197 return result;
198 }
199 ExportResult result = ExportResult.NewInstance(config.getResultType());
200 if (! config.isValid()){
201 String message = "Configuration is not valid";
202 logger.error(message);
203 result.addError(message);
204 result.setAborted();
205 return result;
206 }
207
208 System.out.println("Start export from source '" + config.getSourceNameString()
209 + "' to destination '" + config.getDestinationNameString() + "'");
210
211 ExportStateBase state = config.getNewState();
212 state.initialize(config);
213 state.setResult(result);
214
215 List<ICdmExport> ioList = makeIoList(state, config);
216
217 List<Integer> stepCounts = countSteps(state, ioList);
218 Integer totalCount = stepCounts.get(stepCounts.size()-1);
219 config.getProgressMonitor().beginTask("Start Export", totalCount);
220 config.getProgressMonitor().worked(1);
221 IProgressMonitor parentMonitor = SubProgressMonitor
222 .NewStarted(config.getProgressMonitor(), 99, "Process data", totalCount);
223
224 //do invoke for each class
225 for (int i = 0; i< ioList.size(); i++){
226 ICdmExport export = ioList.get(i);
227 Integer counts = stepCounts.get(i);
228 try {
229 String ioName = export.getClass().getSimpleName();
230 SubProgressMonitor ioMonitor = SubProgressMonitor
231 .NewStarted(parentMonitor, counts, ioName, counts );
232 // state.getConfig().setProgressMonitor(ioMonitor);
233 state.setCurrentIO(export);
234 export.invoke(state);
235 ioMonitor.done();
236 } catch (Exception e) {
237 String message = "Unexpected exception in " + export.getClass().getSimpleName()+ ": " + e.getMessage();
238 logger.error(message);
239 e.printStackTrace();
240 result.addException(e, message);
241 }
242 }
243
244 System.out.println("End export from source '" + config.getSourceNameString()
245 + "' to destination '" + config.getDestinationNameString() + "' "
246 + "("+ result.toString() + ")"
247 ) ;
248 return result;
249 }
250
251 /**
252 * @param state
253 * @param ioList
254 * @return
255 */
256 private List<Integer> countSteps(ExportStateBase state, List<ICdmExport> ioList) {
257 //do invoke for each class
258 List<Integer> result = new ArrayList<>();
259 int sum = 0;
260 for (ICdmExport export: ioList){
261 int count = 1;
262 try {
263 // state.setCurrentIO(export);
264 count = ((Long)export.countSteps(state)).intValue();
265 } catch (Exception e) {
266 String message = "Unexpected exception when count steps for progress monitoring " + export.getClass().getSimpleName()+ ": " + e.getMessage();
267 logger.error(message);
268 e.printStackTrace();
269 state.getResult().addException(e, message);
270 }
271 result.add(count);
272 sum += count;
273 }
274 result.add(sum);
275 return result;
276 }
277
278
279 /**
280 * @param state
281 * @param config
282 * @return
283 */
284 private <CONFIG extends T> List<ICdmExport> makeIoList(ExportStateBase state, CONFIG config) {
285
286 List<ICdmExport> result = new ArrayList<>();
287
288 for (Class<ICdmExport> ioClass: config.getIoClassList()){
289 try {
290 String ioBeanName = getComponentBeanName(ioClass);
291 ICdmExport cdmIo = applicationContext.getBean(ioBeanName, ICdmExport.class);
292 if (cdmIo != null){
293 result.add(cdmIo);
294 }else{
295 String message = "cdmIO was null: " + ioBeanName;
296 logger.error(message);
297 state.getResult().addError(message);
298 }
299 } catch (Exception e) {
300 String message = "Unexpected exception in " + ioClass.getSimpleName()+ ": " + e.getMessage();
301 logger.error(message);
302 e.printStackTrace();
303 state.getResult().addException(e, message);
304 }
305 }
306 return result;
307 }
308
309
310 private String getComponentBeanName(Class<ICdmExport> ioClass){
311 Component component = ioClass.getAnnotation(Component.class);
312 String ioBean = component.value();
313 if ("".equals(ioBean)){
314 ioBean = ioClass.getSimpleName();
315 ioBean = ioBean.substring(0, 1).toLowerCase() + ioBean.substring(1); //make camelcase
316 }
317 return ioBean;
318 }
319
320 }