minor
[cdmlib.git] / cdmlib-io / src / main / java / eu / etaxonomy / cdm / io / common / CdmIoBase.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.lang.reflect.Constructor;
13 import java.lang.reflect.InvocationTargetException;
14 import java.util.HashSet;
15 import java.util.Set;
16
17 import org.apache.commons.lang.StringUtils;
18 import org.apache.log4j.Logger;
19 import org.hibernate.SessionFactory;
20 import org.springframework.beans.factory.annotation.Autowired;
21 import org.springframework.transaction.PlatformTransactionManager;
22 import org.springframework.transaction.TransactionDefinition;
23 import org.springframework.transaction.TransactionStatus;
24 import org.springframework.transaction.support.DefaultTransactionDefinition;
25
26 import eu.etaxonomy.cdm.api.application.CdmApplicationDefaultConfiguration;
27 import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
28 import eu.etaxonomy.cdm.io.common.events.IIoEvent;
29 import eu.etaxonomy.cdm.io.common.events.IIoObserver;
30 import eu.etaxonomy.cdm.io.common.events.IoProblemEvent;
31 import eu.etaxonomy.cdm.io.common.events.IoProgressEvent;
32 import eu.etaxonomy.cdm.model.common.CdmBase;
33
34 /**
35 * @author a.mueller
36 * @created 01.07.2008
37 * @version 1.0
38 */
39 public abstract class CdmIoBase<STATE extends IoStateBase> extends CdmApplicationDefaultConfiguration
40 implements ICdmIO<STATE>, IIoObservable {
41 private static final Logger logger = Logger.getLogger(CdmIoBase.class);
42
43 private Set<IIoObserver> observers = new HashSet<IIoObserver>();
44 protected String ioName = null;
45
46
47 /**
48 *
49 */
50 public CdmIoBase() {
51 super();
52 this.ioName = this.getClass().getSimpleName();
53 }
54
55 //******************** Observers *********************************************************
56
57 @Override
58 public boolean addObserver(IIoObserver observer){
59 return observers.add(observer);
60 }
61
62 /* (non-Javadoc)
63 * @see eu.etaxonomy.cdm.io.common.IIoObservable#getObservers()
64 */
65 @Override
66 public Set<IIoObserver> getObservers() {
67 return observers;
68 }
69
70 /* (non-Javadoc)
71 * @see eu.etaxonomy.cdm.io.common.IIoObservable#addObservers(java.util.Set)
72 */
73 @Override
74 public void addObservers(Set<IIoObserver> newObservers) {
75 for (IIoObserver observer : newObservers){
76 this.observers.add(observer);
77 }
78 }
79
80
81 /* (non-Javadoc)
82 * @see eu.etaxonomy.cdm.io.common.IIoObservable#countObservers()
83 */
84 @Override
85 public int countObservers(){
86 return observers.size();
87 }
88
89
90 /* (non-Javadoc)
91 * @see eu.etaxonomy.cdm.io.common.IIoObservable#removeObserver(eu.etaxonomy.cdm.io.common.events.IIoObserver)
92 */
93 public boolean removeObserver(IIoObserver observer){
94 return observers.remove(observer);
95 }
96
97 /* (non-Javadoc)
98 * @see eu.etaxonomy.cdm.io.common.IIoObservable#removeObservers()
99 */
100 public void removeObservers(){
101 observers.removeAll(observers);
102 }
103
104
105 /* (non-Javadoc)
106 * @see eu.etaxonomy.cdm.io.common.ICdmIO#fire(eu.etaxonomy.cdm.io.common.events.IIoEvent)
107 */
108 public void fire(IIoEvent event){
109 for (IIoObserver observer: observers){
110 observer.handleEvent(event);
111 }
112 }
113
114 //******************** End Observers *********************************************************
115
116
117
118 public int countSteps(){
119 return 1;
120 }
121
122
123 /* (non-Javadoc)
124 * @see eu.etaxonomy.cdm.io.common.ICdmExport#invoke(eu.etaxonomy.cdm.io.common.ExportStateBase)
125 */
126 public boolean invoke(STATE state) {
127 if (isIgnore( state)){
128 logger.info("No invoke for " + ioName + " (ignored)");
129 return true;
130 }else{
131 updateProgress(state, "Invoking " + ioName);
132 doInvoke(state);
133 return state.isSuccess();
134 }
135 }
136
137 /**
138 * invoke method to be implemented by implementing classes
139 * @param state
140 * @return
141 */
142 protected abstract void doInvoke(STATE state);
143
144
145 @Autowired
146 SessionFactory sessionFactory;
147
148 /**
149 * flush the current session
150 */
151 public void flush() {
152 sessionFactory.getCurrentSession().flush();
153 }
154
155 /* (non-Javadoc)
156 * @see eu.etaxonomy.cdm.api.application.CdmApplicationDefaultConfiguration#startTransaction()
157 */
158 public TransactionStatus startTransaction() {
159 return startTransaction(false);
160 }
161
162 /* (non-Javadoc)
163 * @see eu.etaxonomy.cdm.api.application.CdmApplicationDefaultConfiguration#startTransaction(java.lang.Boolean)
164 */
165 public TransactionStatus startTransaction(Boolean readOnly) {
166
167 DefaultTransactionDefinition defaultTxDef = new DefaultTransactionDefinition();
168 defaultTxDef.setReadOnly(readOnly);
169 TransactionDefinition txDef = defaultTxDef;
170
171 // Log some transaction-related debug information.
172 if (logger.isDebugEnabled()) {
173 logger.debug("Transaction name = " + txDef.getName());
174 logger.debug("Transaction facets:");
175 logger.debug("Propagation behavior = " + txDef.getPropagationBehavior());
176 logger.debug("Isolation level = " + txDef.getIsolationLevel());
177 logger.debug("Timeout = " + txDef.getTimeout());
178 logger.debug("Read Only = " + txDef.isReadOnly());
179 // org.springframework.orm.hibernate3.HibernateTransactionManager
180 // provides more transaction/session-related debug information.
181 }
182
183 TransactionStatus txStatus = super.getTransactionManager().getTransaction(txDef);
184 return txStatus;
185 }
186
187 public void commitTransaction(TransactionStatus txStatus){
188 PlatformTransactionManager txManager = super.getTransactionManager();
189 txManager.commit(txStatus);
190 return;
191 }
192
193 public void rollbackTransaction(TransactionStatus txStatus){
194 PlatformTransactionManager txManager = super.getTransactionManager();
195 txManager.rollback(txStatus);
196 return;
197 }
198
199 /* (non-Javadoc)
200 * @see eu.etaxonomy.cdm.io.common.ICdmIO#check(eu.etaxonomy.cdm.io.common.IIoConfigurator)
201 */
202 public boolean check(STATE state) {
203 if (isIgnore(state)){
204 logger.info("No check for " + ioName + " (ignored)");
205 return true;
206 }else{
207 return doCheck(state);
208 }
209 }
210
211 protected abstract boolean doCheck(STATE state);
212
213
214 /* (non-Javadoc)
215 * @see eu.etaxonomy.cdm.io.common.ICdmIO#invoke(eu.etaxonomy.cdm.io.common.IIoConfigurator, java.util.Map)
216 */
217 // public boolean invoke(T config,
218 // Map<String, MapWrapper<? extends CdmBase>> stores) {
219 // if (isIgnore(config)){
220 // logger.warn("No invoke for " + ioName + " (ignored)");
221 // return true;
222 // }else{
223 // return doInvoke(config, stores);
224 // }
225 // }
226
227 // protected abstract boolean doInvoke(T config,
228 // Map<String, MapWrapper<? extends CdmBase>> stores);
229
230
231 /**
232 * Returns true if this (IO-)class should be ignored during the import/export process.
233 * This information is usually stored in the configuration
234 * @param config
235 * @return
236 */
237 protected abstract boolean isIgnore(STATE state);
238
239 protected <T extends CdmBase> T getInstance(Class<? extends T> clazz){
240 T result = null;
241 try {
242 Constructor<? extends T> constructor = clazz.getDeclaredConstructor();
243 constructor.setAccessible(true);
244 result = constructor.newInstance();
245 } catch (InstantiationException e) {
246 logger.error("Class " + clazz.getSimpleName()+" could not be instantiated. Class = " );
247 e.printStackTrace();
248 } catch (IllegalAccessException e) {
249 logger.error("Constructor of class "+clazz.getSimpleName()+" could not be accessed." );
250 e.printStackTrace();
251 } catch (SecurityException e) {
252 e.printStackTrace();
253 } catch (NoSuchMethodException e) {
254 logger.error("SecurityException for Constructor of class "+clazz.getSimpleName()+"." );
255 e.printStackTrace();
256 } catch (IllegalArgumentException e) {
257 logger.error("Empty Constructor does not exist for class "+clazz.getSimpleName()+"." );
258 e.printStackTrace();
259 } catch (InvocationTargetException e) {
260 logger.error("Empty Constructor could not be invoked for class "+clazz.getSimpleName()+"." );
261 e.printStackTrace();
262 }
263 return result;
264 }
265
266
267 protected String getSuccessString(boolean success){
268 if (success){
269 return "with success";
270 }else{
271 return "with errors";
272 }
273 }
274
275 @Override
276 public void updateProgress(STATE state, String message) {
277 updateProgress(state, message, 1);
278 };
279
280 @Override
281 public void updateProgress(STATE state, String message, int worked) {
282 IProgressMonitor progressMonitor = state.getConfig().getProgressMonitor();
283 if(progressMonitor != null){
284 progressMonitor.worked(worked);
285 progressMonitor.subTask(message);
286 }
287 }
288
289 @Override
290 public void warnProgress(STATE state, String message, Throwable e) {
291 if(state.getConfig().getProgressMonitor() != null){
292 IProgressMonitor monitor = state.getConfig().getProgressMonitor();
293 if (e == null) {
294 monitor.warning(message);
295 }else{
296 monitor.warning(message, e);
297 }
298 }
299 }
300
301 protected void fireProgressEvent(String message, String location) {
302 IoProgressEvent event = new IoProgressEvent();
303 event.setThrowingClass(this.getClass());
304 event.setMessage(message);
305 event.setLocation(location);
306 // int linenumber = new Exception().getStackTrace()[0].getLineNumber();
307 fire(event);
308 }
309
310
311 protected void fireWarningEvent(String message, String dataLocation, Integer severity) {
312 fireWarningEvent(message, dataLocation, severity, 1);
313 }
314
315 protected void fireWarningEvent(String message, String dataLocation, Integer severity, int stackDepth) {
316 stackDepth++;
317 StackTraceElement[] stackTrace = new Exception().getStackTrace();
318 int lineNumber = stackTrace[stackDepth].getLineNumber();
319 String methodName = stackTrace[stackDepth].getMethodName();
320
321 IoProblemEvent event = IoProblemEvent.NewInstance(this.getClass(), message, dataLocation,
322 lineNumber, severity, methodName);
323
324 //for performance improvement one may read:
325 //http://stackoverflow.com/questions/421280/in-java-how-do-i-find-the-caller-of-a-method-using-stacktrace-or-reflection
326 // Object o = new SecurityManager().getSecurityContext();
327
328
329 fire(event);
330 }
331
332 protected boolean isBlank(String str){
333 return StringUtils.isBlank(str);
334 }
335
336 protected boolean isNotBlank(String str){
337 return StringUtils.isNotBlank(str);
338 }
339
340
341 // /**
342 // * Returns the first stack trace element of the first class not equal to "StackTraceUtils" or "LogUtils" and aClass. <br />
343 // * Stored in array of the callstack. <br />
344 // * Allows to get past a certain class.
345 // * @param aclass class to get pass in the stack trace. If null, only try to get past StackTraceUtils.
346 // * @return stackTraceElement (never null, because if aClass is not found, returns first class past StackTraceUtils)
347 // * @throws AssertionFailedException if resulting statckTrace is null (RuntimeException)
348 // */
349 // public static StackTraceElement getCallingStackTraceElement(final Class aclass) {
350 // final Throwable t = new Throwable();
351 // final StackTraceElement[] ste = t.getStackTrace();
352 // int index = 1;
353 // final int limit = ste.length;
354 // StackTraceElement st = ste[index];
355 // String className = st.getClassName();
356 // boolean aclassfound = false;
357 // if(aclass == null) {
358 // aclassfound = true;
359 // }
360 // StackTraceElement resst = null;
361 // while(index < limit) {
362 // if(shouldExamine(className, aclass) == true) {
363 // if(resst == null) {
364 // resst = st;
365 // }
366 // if(aclassfound == true) {
367 // final StackTraceElement ast = onClassFound(aclass, className, st);
368 // if(ast != null) {
369 // resst = ast;
370 // break;
371 // }
372 // }
373 // else
374 // {
375 // if(aclass != null && aclass.getName().equals(className) == true) {
376 // aclassfound = true;
377 // }
378 // }
379 // }
380 // index = index + 1;
381 // st = ste[index];
382 // className = st.getClassName();
383 // }
384 // if(resst == null) {
385 // throw new AssertionFailedException(StackTraceUtils.getClassMethodLine() + " null argument:" + "stack trace should null"); //$NON-NLS-1$
386 // }
387 // return resst;
388 // }
389 //
390 // static private boolean shouldExamine(String className, Class aclass) {
391 // final boolean res = StackTraceUtils.class.getName().equals(className) == false && (className.endsWith(LOG_UTILS
392 // ) == false || (aclass !=null && aclass.getName().endsWith(LOG_UTILS)));
393 // return res;
394 // }
395 //
396 // static private StackTraceElement onClassFound(Class aclass, String className, StackTraceElement st) {
397 // StackTraceElement resst = null;
398 // if(aclass != null && aclass.getName().equals(className) == false)
399 // {
400 // resst = st;
401 // }
402 // if(aclass == null)
403 // {
404 // resst = st;
405 // }
406 // return resst;
407 // }
408
409
410 }