001// ______________________________________________________
002// Generated by sql2java - https://github.com/10km/sql2java-2-6-7 (custom branch) 
003// modified by guyadong from
004// sql2java original version https://sourceforge.net/projects/sql2java/ 
005// JDBC driver used at code generation time: com.mysql.jdbc.Driver
006// template: tablelistener.java.vm
007// ______________________________________________________
008package net.gdface.facelog.db;
009
010import java.util.LinkedHashSet;
011import java.util.LinkedList;
012import java.util.Set;
013import java.util.concurrent.Executor;
014
015import net.gdface.facelog.db.exception.RuntimeDaoException;
016
017/**
018 * Listener that is notified of table changes.
019 * @author guyadong
020 */
021public interface TableListener<B>{
022    /**
023     * This adapter class provides default implementations for the
024     * methods declared by the {@link TableListener} interface.<br>
025     * 
026     * @author guyadong
027     */
028    public static class Adapter<B> implements TableListener<B>{
029
030        @Override
031        public void beforeInsert(B bean)throws RuntimeDaoException {}
032
033        @Override
034        public void afterInsert(B bean)throws RuntimeDaoException {}
035
036        @Override
037        public void beforeUpdate(B bean)throws RuntimeDaoException {}
038
039        @Override
040        public void afterUpdate(B bean)throws RuntimeDaoException {}
041
042        @Override
043        public void beforeDelete(B bean)throws RuntimeDaoException {}
044
045        @Override
046        public void afterDelete(B bean)throws RuntimeDaoException {}
047        
048        @Override
049        public void done()throws RuntimeDaoException {}
050    }
051    /**
052     * Invoked just before inserting a B record into the database.
053     *
054     * @param bean the B that is about to be inserted
055     * @throws RuntimeDaoException
056     */
057    public void beforeInsert(B bean)throws RuntimeDaoException;
058
059
060    /**
061     * Invoked just after a B record is inserted in the database.
062     *
063     * @param bean the B that was just inserted
064     * @throws RuntimeDaoException
065     */
066    public void afterInsert(B bean)throws RuntimeDaoException;
067
068
069    /**
070     * Invoked just before updating a B record in the database.
071     *
072     * @param bean the B that is about to be updated
073     * @throws RuntimeDaoException
074     */
075    public void beforeUpdate(B bean)throws RuntimeDaoException;
076
077
078    /**
079     * Invoked just after updating a B record in the database.
080     *
081     * @param bean the B that was just updated
082     * @throws RuntimeDaoException
083     */
084    public void afterUpdate(B bean)throws RuntimeDaoException;
085
086
087    /**
088     * Invoked just before deleting a B record in the database.
089     *
090     * @param bean the B that is about to be deleted
091     * @throws RuntimeDaoException
092     */
093    public void beforeDelete(B bean)throws RuntimeDaoException;
094
095
096    /**
097     * Invoked just after deleting a B record in the database.
098     *
099     * @param bean the B that was just deleted
100     * @throws RuntimeDaoException
101     */
102    public void afterDelete(B bean)throws RuntimeDaoException;
103
104    /**
105     * Invoked in finally block, just after insert,update,delete.
106     *
107     * @throws RuntimeDaoException
108     */
109    public void done()throws RuntimeDaoException;
110
111    /**
112     * listener event:<br>
113     * {@code INSERT} insert a bean<br>
114     * {@code UPDATE} update a bean<br>
115     * {@code DELETE} delete a bean<br>
116     * {@code UPDATE_BEFORE} before updating a bean<br>
117     * @author guyadong
118     *
119     */
120    public static enum Event{        
121        /** insert a bean */INSERT,
122        /** update a bean */UPDATE,
123        /** delete a bean */DELETE,
124        /** before updating a bean */UPDATE_BEFORE,;
125        /**
126         * fire current event by  {@link ListenerContainer}
127         * @param container
128         * @param bean
129         * @throws RuntimeDaoException
130         */
131        public <B> void fire(ListenerContainer<B> container,B bean)throws RuntimeDaoException {
132            if(null == container || null == bean){
133                return;
134            }
135            switch(this){
136            case INSERT:
137                container.afterInsert(bean);
138                break;
139            case UPDATE:
140                container.afterUpdate(bean);
141                break;
142            case DELETE:
143                container.afterDelete(bean);
144                break;
145            case UPDATE_BEFORE:
146                container.beforeUpdate(bean);
147                break;
148            default:
149                break;
150            }
151        }
152        public <B extends BaseBean<B>> void fire(TableManager<B > manager,B bean)throws RuntimeDaoException {
153            if(null == manager || null == bean){
154                return;
155            }
156            manager.fire(this, bean);
157        }
158    }
159    /** 
160     * container for multiple listener management
161     * @author guyadong 
162     */
163    public static class ListenerContainer <B> implements TableListener<B> {
164        private final Set<TableListener<B>> listeners = new LinkedHashSet<TableListener<B>>(16);
165        private static final InheritableThreadLocal<LinkedList<Runnable>> commitTasks = new InheritableThreadLocal<>();
166        
167        public static final TransactionListener TRANSACTION_LISTENER = new TransactionListener() {
168
169            @Override
170            public void beginTransaction() {
171                commitTasks.set(new LinkedList<Runnable>());
172            }
173
174            @Override
175            public void endTransaction(boolean commit) {
176                if(commit){
177                    if(null == commitTasks.get()){
178                        throw new IllegalStateException("'beginTransaction' must be called firstly");
179                    }
180                    for (Runnable task : commitTasks.get()) {
181                        task.run();
182                    }
183                }
184                commitTasks.remove();
185            }
186        };
187        public ListenerContainer() {
188        }
189    
190        private static void runTask(Runnable task){
191            if(commitTasks.get() != null){
192                commitTasks.get().add(task);
193            }else {
194                task.run();
195            }
196        }
197        @Override
198        public void beforeInsert(B bean)throws RuntimeDaoException{
199            synchronized (listeners) {
200                for(TableListener<B> listener:listeners){
201                    try{
202                        listener.beforeInsert(bean);
203                    }catch(Exception e){
204                        System.out.printf("beforeInsert listener error:%s\n",e.getMessage());
205                    }
206                }
207            }
208        }
209    
210        @Override
211        public void afterInsert(final B bean)throws RuntimeDaoException{
212            synchronized (listeners) {
213                for(final TableListener<B> listener:listeners){
214                    runTask(new Runnable() {
215                        
216                        @Override
217                        public void run() {
218                            try{
219                                listener.afterInsert(bean);
220                            }catch(Exception e){
221                                System.out.printf("afterInsert listener error:%s\n",e.getMessage());
222                            }
223                        }
224                    });
225
226                }
227            }
228        }
229    
230        @Override
231        public void beforeUpdate(B bean)throws RuntimeDaoException{
232            synchronized (listeners) {
233                for(TableListener<B> listener:listeners){
234                    try{
235                        listener.beforeUpdate(bean);
236                    }catch(Exception e){
237                        System.out.printf("beforeUpdate listener error:%s\n",e.getMessage());
238                    }
239                }
240            }
241        }
242    
243        @Override
244        public void afterUpdate(final B bean)throws RuntimeDaoException{
245            synchronized (listeners) {
246                for(final TableListener<B> listener:listeners){
247                    runTask(new Runnable() {
248                        
249                        @Override
250                        public void run() {
251                            try{
252                                listener.afterUpdate(bean);
253                            }catch(Exception e){
254                                System.out.printf("afterUpdate listener error:%s\n",e.getMessage());
255                            }
256                        }
257                    });
258
259                }
260            }
261        }
262    
263        @Override
264        public void beforeDelete(B bean)throws RuntimeDaoException{
265            synchronized (listeners) {
266                for(TableListener<B> listener:listeners){
267                    try{
268                        listener.beforeDelete(bean);
269                    }catch(Exception e){
270                        System.out.printf("beforeDelete listener error:%s\n",e.getMessage());
271                    }
272                }
273            }
274        }
275    
276        @Override
277        public void afterDelete(final B bean)throws RuntimeDaoException{
278            synchronized (listeners) {
279                for(final TableListener<B> listener:listeners){
280                    runTask(new Runnable() {
281                        
282                        @Override
283                        public void run() {
284                            try{
285                                listener.afterDelete(bean);
286                            }catch(Exception e){
287                                System.out.printf("afterDelete listener error:%s\n",e.getMessage());
288                            }
289                        }
290                    });
291
292                }
293            }
294        }
295
296        @Override
297        public void done()throws RuntimeDaoException{
298            synchronized (listeners) {
299                for(TableListener<B> listener:listeners){
300                    try{
301                        listener.done();
302                    }catch(Exception e){
303                        System.out.printf("done listener error:%s\n",e.getMessage());
304                    }
305                }
306            }
307        }
308        /**
309         * determine if the container is empty.
310         * @return 
311         */
312        public boolean isEmpty() {
313            return listeners.isEmpty();
314        }
315        /**
316         * determine if the {@code listener} be added.
317         * @param listener
318         * @return {@code true} if {@code listener} exists in container
319         */
320        public boolean contains(TableListener<B> listener) {
321            synchronized (listeners) {
322                return listeners.contains(listener);
323            }
324        }
325        /**
326         * add {@code listener} into container
327         * @return {@code true} if add successfully.
328         */
329        public boolean add(TableListener<B> listener) {
330            synchronized (listeners) {
331                return null == listener ? false : listeners.add(listener);
332            }
333        }
334        /**
335         * remove {@code listener} from container
336         * @param listener instance that will be removed.
337         * @return {@code true} if remove successfully.
338         */
339        public boolean remove(TableListener<B> listener) {
340            synchronized (listeners) {
341                return null == listener? false : listeners.remove(listener);
342            }
343        }
344        /** remove all listeners in container */
345        public void clear() {
346            synchronized (listeners) {
347                listeners.clear();
348            }
349        }
350    }
351    /**
352     * decorator of a {@link TableListener}<br>
353     * run {@code delegate} in {@link Executor}
354     * @author guyadong
355     *
356     * @param <B>
357     */
358    public static class DecoratorExecutorListener<B> implements TableListener<B>{
359        private final TableListener<B> delegate;
360        private static final Executor DIRECT_EXECUTOR= new Executor(){
361            @Override
362            public void execute(Runnable command) {
363                command.run();
364            }};
365        public DecoratorExecutorListener(TableListener<B> delegate) {
366            if(null == delegate){
367                throw new NullPointerException();
368            }
369            this.delegate = delegate;
370        }
371        /** return a {@link Executor} instance for execute task */
372        protected  Executor getExecutor() {
373            return DIRECT_EXECUTOR;
374        }
375        public TableListener<B> delegate(){
376            return delegate;
377        }
378        protected void onException(Exception e){
379            e.printStackTrace();
380        }
381        @Override
382        public void beforeInsert(final B bean) throws RuntimeDaoException {
383            getExecutor().execute(new Runnable(){
384                @Override
385                public void run() {
386                    try{
387                        delegate.beforeDelete(bean);
388                    }catch(Exception e){
389                        onException(e);
390                    }
391                }});
392        }
393
394        @Override
395        public void afterInsert(final B bean) throws RuntimeDaoException {
396            getExecutor().execute(new Runnable(){
397                @Override
398                public void run() {
399                    try{
400                        delegate.afterInsert(bean);
401                    }catch(Exception e){
402                        onException(e);
403                    }
404                }});
405        }
406
407        @Override
408        public void beforeUpdate(final B bean) throws RuntimeDaoException {
409            getExecutor().execute(new Runnable(){
410                @Override
411                public void run() {
412                    try{
413                        delegate.beforeUpdate(bean);
414                    }catch(Exception e){
415                        onException(e);
416                    }
417                }});
418        }
419
420        @Override
421        public void afterUpdate(final B bean) throws RuntimeDaoException {
422            getExecutor().execute(new Runnable(){
423                @Override
424                public void run() {
425                    try{
426                        delegate.afterUpdate(bean);
427                    }catch(Exception e){
428                        onException(e);
429                    }
430                }});
431        }
432
433        @Override
434        public void beforeDelete(final B bean) throws RuntimeDaoException {
435            getExecutor().execute(new Runnable(){
436                @Override
437                public void run() {
438                    try{
439                        delegate.beforeDelete(bean);
440                    }catch(Exception e){
441                        onException(e);
442                    }
443                }});
444        }
445
446        @Override
447        public void afterDelete(final B bean) throws RuntimeDaoException {
448            getExecutor().execute(new Runnable(){
449                @Override
450                public void run() {
451                    try{
452                        delegate.afterDelete(bean);
453                    }catch(Exception e){
454                        onException(e);
455                    }
456                }});
457        }
458
459        @Override
460        public void done() throws RuntimeDaoException {
461            getExecutor().execute(new Runnable(){
462                @Override
463                public void run() {
464                    try{
465                        delegate.done();
466                    }catch(Exception e){
467                        onException(e);
468                    }
469                }});
470        }
471    }
472    public static interface TransactionListener{
473        public void beginTransaction();
474        public void endTransaction(boolean commit);
475    }
476}
477