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 */
38 public abstract class CdmIoBase<STATE extends IoStateBase> extends CdmApplicationDefaultConfiguration
39 implements ICdmIO<STATE>, IIoObservable {
40 private static final Logger logger = Logger.getLogger(CdmIoBase.class);
41
42 private final Set<IIoObserver> observers = new HashSet<IIoObserver>();
43 protected String ioName = null;
44
45
46 /**
47 *
48 */
49 public CdmIoBase() {
50 super();
51 this.ioName = this.getClass().getSimpleName();
52 }
53
54 //******************** Observers *********************************************************
55
56 @Override
57 public boolean addObserver(IIoObserver observer){
58 return observers.add(observer);
59 }
60
61 @Override
62 public Set<IIoObserver> getObservers() {
63 return observers;
64 }
65
66 @Override
67 public void addObservers(Set<IIoObserver> newObservers) {
68 for (IIoObserver observer : newObservers){
69 this.observers.add(observer);
70 }
71 }
72
73 @Override
74 public int countObservers(){
75 return observers.size();
76 }
77
78 @Override
79 public boolean removeObserver(IIoObserver observer){
80 return observers.remove(observer);
81 }
82
83 @Override
84 public void removeObservers(){
85 observers.removeAll(observers);
86 }
87
88 @Override
89 public void fire(IIoEvent event){
90 for (IIoObserver observer: observers){
91 observer.handleEvent(event);
92 }
93 }
94
95 //******************** End Observers *********************************************************
96
97
98 public int countSteps(){
99 return 1;
100 }
101
102 @Override
103 public boolean invoke(STATE state) {
104 if (isIgnore( state)){
105 logger.info("No invoke for " + ioName + " (ignored)");
106 return true;
107 }else{
108 updateProgress(state, "Invoking " + ioName);
109 doInvoke(state);
110 return state.isSuccess();
111 }
112 }
113
114 /**
115 * invoke method to be implemented by implementing classes
116 * @param state
117 * @return
118 */
119 protected abstract void doInvoke(STATE state);
120
121 @Autowired
122 private SessionFactory sessionFactory;
123
124 /**
125 * flush the current session
126 */
127 //TODO move into super class CdmApplicationDefaultConfiguration#flush() ?
128 public void flush() {
129 sessionFactory.getCurrentSession().flush();
130 }
131
132 @Override
133 //TODO seems to be exact duplicate of CdmApplicationDefaultConfiguration#startTransaction(), remove duplicate
134 public TransactionStatus startTransaction() {
135 return startTransaction(false);
136 }
137
138 @Override
139 //TODO seems to be exact duplicate of CdmApplicationDefaultConfiguration#startTransaction(java.lang.Boolean)
140 public TransactionStatus startTransaction(Boolean readOnly) {
141
142 DefaultTransactionDefinition defaultTxDef = new DefaultTransactionDefinition();
143 defaultTxDef.setReadOnly(readOnly);
144 TransactionDefinition txDef = defaultTxDef;
145
146 // Log some transaction-related debug information.
147 if (logger.isDebugEnabled()) {
148 logger.debug("Transaction name = " + txDef.getName());
149 logger.debug("Transaction facets:");
150 logger.debug("Propagation behavior = " + txDef.getPropagationBehavior());
151 logger.debug("Isolation level = " + txDef.getIsolationLevel());
152 logger.debug("Timeout = " + txDef.getTimeout());
153 logger.debug("Read Only = " + txDef.isReadOnly());
154 // org.springframework.orm.hibernate4.HibernateTransactionManager
155 // provides more transaction/session-related debug information.
156 }
157
158 TransactionStatus txStatus = super.getTransactionManager().getTransaction(txDef);
159 return txStatus;
160 }
161
162 @Override
163 //TODO seems to be exact duplicate of CdmApplicationDefaultConfiguration#startTransaction(java.lang.Boolean), remove duplicate?
164 public void commitTransaction(TransactionStatus txStatus){
165 PlatformTransactionManager txManager = super.getTransactionManager();
166 txManager.commit(txStatus);
167 return;
168 }
169
170 //TODO move into super class CdmApplicationDefaultConfiguration#startTransaction(java.lang.Boolean)
171 //==> no
172 public void rollbackTransaction(TransactionStatus txStatus){
173 PlatformTransactionManager txManager = super.getTransactionManager();
174 txManager.rollback(txStatus);
175 return;
176 }
177
178 @Override
179 public boolean check(STATE state) {
180 if (isIgnore(state)){
181 logger.info("No check for " + ioName + " (ignored)");
182 return true;
183 }else{
184 return doCheck(state);
185 }
186 }
187
188 protected abstract boolean doCheck(STATE state);
189
190
191 /**
192 * Returns true if this (IO-)class should be ignored during the import/export process.
193 * This information is usually stored in the configuration
194 * @param config
195 * @return
196 */
197 protected abstract boolean isIgnore(STATE state);
198
199 protected <T extends CdmBase> T getInstance(Class<? extends T> clazz){
200 T result = null;
201 try {
202 Constructor<? extends T> constructor = clazz.getDeclaredConstructor();
203 constructor.setAccessible(true);
204 result = constructor.newInstance();
205 } catch (InstantiationException e) {
206 logger.error("Class " + clazz.getSimpleName()+" could not be instantiated. Class = " );
207 e.printStackTrace();
208 } catch (IllegalAccessException e) {
209 logger.error("Constructor of class "+clazz.getSimpleName()+" could not be accessed." );
210 e.printStackTrace();
211 } catch (SecurityException e) {
212 e.printStackTrace();
213 } catch (NoSuchMethodException e) {
214 logger.error("SecurityException for Constructor of class "+clazz.getSimpleName()+"." );
215 e.printStackTrace();
216 } catch (IllegalArgumentException e) {
217 logger.error("Empty Constructor does not exist for class "+clazz.getSimpleName()+"." );
218 e.printStackTrace();
219 } catch (InvocationTargetException e) {
220 logger.error("Empty Constructor could not be invoked for class "+clazz.getSimpleName()+"." );
221 e.printStackTrace();
222 }
223 return result;
224 }
225
226
227 protected String getSuccessString(boolean success){
228 if (success){
229 return "with success";
230 }else{
231 return "with errors";
232 }
233 }
234
235 @Override
236 public void updateProgress(STATE state, String message) {
237 updateProgress(state, message, 1);
238 }
239
240 @Override
241 public void updateProgress(STATE state, String message, int worked) {
242 IProgressMonitor progressMonitor = state.getConfig().getProgressMonitor();
243 if(progressMonitor != null){
244 progressMonitor.worked(worked);
245 progressMonitor.subTask(message);
246 }
247 }
248
249 @Override
250 public void warnProgress(STATE state, String message, Throwable e) {
251 if(state.getConfig().getProgressMonitor() != null){
252 IProgressMonitor monitor = state.getConfig().getProgressMonitor();
253 if (e == null) {
254 monitor.warning(message);
255 }else{
256 monitor.warning(message, e);
257 }
258 }
259 }
260
261 protected void fireProgressEvent(String message, String location) {
262 IoProgressEvent event = new IoProgressEvent();
263 event.setThrowingClass(this.getClass());
264 event.setMessage(message);
265 event.setLocation(location);
266 // int linenumber = new Exception().getStackTrace()[0].getLineNumber();
267 fire(event);
268 }
269
270
271 protected void fireWarningEvent(String message, String dataLocation, Integer severity) {
272 fireWarningEvent(message, dataLocation, severity, 1);
273 }
274
275 protected void fireWarningEvent(String message, String dataLocation, Integer severity, int stackDepth) {
276 stackDepth++;
277 StackTraceElement[] stackTrace = new Exception().getStackTrace();
278 int lineNumber = stackTrace[stackDepth].getLineNumber();
279 String methodName = stackTrace[stackDepth].getMethodName();
280 String className = stackTrace[stackDepth].getClassName();
281 Class<?> declaringClass;
282 try {
283 declaringClass = Class.forName(className);
284 } catch (ClassNotFoundException e) {
285 declaringClass = this.getClass();
286 }
287
288 IoProblemEvent event = IoProblemEvent.NewInstance(declaringClass, message, dataLocation,
289 lineNumber, severity, methodName);
290
291 //for performance improvement one may read:
292 //http://stackoverflow.com/questions/421280/in-java-how-do-i-find-the-caller-of-a-method-using-stacktrace-or-reflection
293 // Object o = new SecurityManager().getSecurityContext();
294
295
296 fire(event);
297 }
298
299 protected boolean isBlank(String str){
300 return StringUtils.isBlank(str);
301 }
302
303 protected boolean isNotBlank(String str){
304 return StringUtils.isNotBlank(str);
305 }
306
307 }