1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.caleigo.core;
19
20 import java.lang.reflect.Method;
21
22 import org.caleigo.core.IDataTransaction.*;
23 import org.caleigo.toolkit.log.Log;
24
25 /***
26 *
27 * @author mha
28 * @version 1.00
29 *
30 */ /*
31 *
32 * WHEN WHO WHY & WHAT
33 * -----------------------------------------------------------------------------
34 * Mar 15, 2004 Mattias Hagstrand Creation
35 */
36 public class AsyncTransactionHandler
37 {
38
39 protected final static int STARTED = 1;
40 protected final static int FINISHED = 2;
41 protected final static int COMPLETED = 3;
42 protected final static int CANCELED = 4;
43 protected final static int FAILED = 5;
44
45 public final static int COMMIT_SUCCEEDED = 1;
46 public final static int COMMIT_CANCELED = 2;
47 public final static int COMMIT_FAILED = 3;
48
49
50 private static Class sDefaultAsyncTransactionHandlerClass;
51
52
53 public static void setDefaultAsyncTransactionHandlerClass(Class handlerClass)
54 {
55 if (!AsyncTransactionHandler.class.isAssignableFrom(handlerClass))
56 throw new IllegalArgumentException("Handler class must be an AsyncTransactionHandler sub class");
57
58 try
59 {
60 handlerClass.getConstructor(new Class[0]);
61 } catch (Exception e)
62 {
63 throw new IllegalArgumentException("Handler class must have a default constructor");
64 }
65
66 sDefaultAsyncTransactionHandlerClass = handlerClass;
67 }
68
69 public static AsyncTransactionHandler create()
70 {
71 if (sDefaultAsyncTransactionHandlerClass == null)
72 throw new IllegalStateException("No default transaction handler has been set");
73
74 AsyncTransactionHandler handler = null;
75 try
76 {
77 handler = (AsyncTransactionHandler) sDefaultAsyncTransactionHandlerClass.getConstructor(new Class[0]).newInstance(new Object[0]);
78 } catch (Exception e)
79 {
80 Log.printError(null, "Failed to create default transaction handler", e);
81 }
82
83 return handler;
84 }
85
86
87 private Object mCallbackObject;
88 private String mCallbackMethodName;
89
90
91
92
93
94 /*** Sets the method that should be invoked when the transaction has finished.
95 * This method is invoked before the corresponding doOn-method is invoked.
96 *
97 * Note: The callback method must not declare one int parameter that will be
98 * set to one of COMMIT_SUCCEEDED, COMMIT_CANCELED or COMMIT_FAILED.
99 */
100 public void setCallback(Object callbackObject, String methodName)
101 {
102 if (callbackObject == null)
103 throw new IllegalArgumentException("callbackObject must not be null");
104 if (methodName == null)
105 throw new IllegalArgumentException("methodName must not be null");
106
107 try
108 {
109 callbackObject.getClass().getMethod(methodName, new Class[] {Integer.TYPE});
110 } catch (Exception e)
111 {
112 throw new IllegalArgumentException("The callback method was not found");
113 }
114
115 mCallbackObject = callbackObject;
116 mCallbackMethodName = methodName;
117 }
118
119 public Job commit(IDataTransaction transaction)
120 {
121 Job job = transaction.commitAsynchroniesly(null);
122 job.addProgressListener(new ProgressListener());
123
124 return job;
125 }
126
127
128
129 /*** Invoked when the commit execution starts.
130 */
131 protected void doOnCommitStarted()
132 {
133 }
134
135 /*** Invoked when the commit execution has finished. Execution finishes when
136 * the commit has completed, has been canceled or has failed. This method is
137 * invoked before one of doOnCommitCompleted, doOnCommitCanceled or
138 * doOnCommitFailed is invoked.
139 */
140 protected void doOnCommitFinished()
141 {
142 }
143
144 /*** Invoked when the commit execution has completed.
145 */
146 protected void doOnCommitCompleted()
147 {
148 }
149
150 /*** Invoked when the commit execution has been successfully canceled.
151 */
152 protected void doOnCommitCanceled()
153 {
154 }
155
156 /*** Invoked when the commit execution has failed.
157 */
158 protected void doOnCommitFailed()
159 {
160 }
161
162 /*** Invoked when one of the doOn-methods should be invoked. Extending classes
163 * should not change the behaviour of this method, but should make sure that
164 * it is executed in a thread safe manner. Typically, is GUI operations needs
165 * to be performed in the doOn-methods this method should be run in the dispatcher
166 * thread.
167 */
168 protected void performNotification(int type)
169 {
170 switch (type)
171 {
172 case STARTED:
173 this.doOnCommitStarted();
174 break;
175 case FINISHED:
176 this.doOnCommitFinished();
177 break;
178 case COMPLETED:
179 this.invokeCallback(COMMIT_SUCCEEDED);
180 this.doOnCommitCompleted();
181 break;
182 case CANCELED:
183 this.invokeCallback(COMMIT_CANCELED);
184 this.doOnCommitCanceled();
185 break;
186 case FAILED:
187 this.invokeCallback(COMMIT_FAILED);
188 this.doOnCommitFailed();
189 break;
190 }
191 }
192
193 private void invokeCallback(int status)
194 {
195 if (mCallbackObject != null)
196 {
197 try
198 {
199 Method callbackMethod = mCallbackObject.getClass().getMethod(mCallbackMethodName, new Class[] {Integer.TYPE});
200 callbackMethod.invoke(mCallbackObject, new Object[] {new Integer(status)});
201 } catch (Exception e)
202 {
203 Log.printError(this, "Failed to invoke callback", e);
204 }
205 }
206 }
207
208
209 private class ProgressListener implements IDataTransaction.IProgressListener
210 {
211 public void jobStarted(ProgressEvent e)
212 {
213 performNotification(STARTED);
214 }
215
216 public void jobCompleted(ProgressEvent e)
217 {
218 performNotification(FINISHED);
219 performNotification(COMPLETED);
220 }
221
222 public void jobCanceled(ProgressEvent e)
223 {
224 performNotification(FINISHED);
225 performNotification(CANCELED);
226 }
227
228 public void jobFailed(ProgressEvent e)
229 {
230 performNotification(FINISHED);
231 performNotification(FAILED);
232 }
233
234 public void progressChanged(ProgressEvent e)
235 {
236 }
237 }
238 }