gu.sql2java.ListenerContainer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sql2java-manager Show documentation
Show all versions of sql2java-manager Show documentation
sql2java manager class package for accessing database
package gu.sql2java;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import com.google.common.collect.ImmutableList;
import gu.sql2java.exception.RuntimeDaoException;
import static com.google.common.base.Preconditions.*;
import static gu.sql2java.SimpleLog.*;
/**
* container for multiple listener management
* @author guyadong
*/
class ListenerContainer implements TableListener {
private final LinkedHashSet> listeners = new LinkedHashSet>(16);
static final TransactionListenerImpl TRANSACTION_LISTENER = new TransactionListenerImpl();
public ListenerContainer() {
}
@Override
public void beforeInsert(B bean)throws RuntimeDaoException{
synchronized (listeners) {
for(TableListener listener:listeners){
try{
listener.beforeInsert(bean);
}catch(Exception e){
log("beforeInsert listener %s error:%s",listener.getClass().getName(),e.getMessage());
if(BaseTableManager.isDebug()){
log(e);
}
}
}
}
}
@Override
public void afterInsert(final B bean)throws RuntimeDaoException{
synchronized (listeners) {
for(final TableListener listener:listeners){
TRANSACTION_LISTENER.runCommitTask(new Runnable() {
@Override
public void run() {
try{
listener.afterInsert(bean);
}catch(Exception e){
log("afterInsert listener %s error:%s",listener.getClass().getName(),e.getMessage());
if(BaseTableManager.isDebug()){
log(e);
}
}
}
});
}
}
}
@Override
public void beforeUpdate(B bean)throws RuntimeDaoException{
synchronized (listeners) {
for(TableListener listener:listeners){
try{
listener.beforeUpdate(bean);
}catch(Exception e){
log("beforeUpdate listener %s error:%s",listener.getClass().getName(),e.getMessage());
if(BaseTableManager.isDebug()){
log(e);
}
}
}
}
}
@Override
public void afterUpdate(final B bean)throws RuntimeDaoException{
synchronized (listeners) {
for(final TableListener listener:listeners){
TRANSACTION_LISTENER.runCommitTask(new Runnable() {
@Override
public void run() {
try{
listener.afterUpdate(bean);
}catch(Exception e){
log("afterUpdate listener %s error:%s",listener.getClass().getName(),e.getMessage());
if(BaseTableManager.isDebug()){
log(e);
}
}
}
});
}
}
}
@Override
public void beforeDelete(B bean)throws RuntimeDaoException{
synchronized (listeners) {
for(TableListener listener:listeners){
try{
listener.beforeDelete(bean);
}catch(Exception e){
log("beforeDelete listener %s error:%s",listener.getClass().getName(),e.getMessage());
if(BaseTableManager.isDebug()){
log(e);
}
}
}
}
}
@Override
public void afterDelete(final B bean)throws RuntimeDaoException{
synchronized (listeners) {
for(final TableListener listener:listeners){
TRANSACTION_LISTENER.runCommitTask(new Runnable() {
@Override
public void run() {
try{
listener.afterDelete(bean);
}catch(Exception e){
log("afterDelete listener %s error:%s",listener.getClass().getName(),e.getMessage());
if(BaseTableManager.isDebug()){
log(e);
}
}
}
});
}
}
}
@Override
public void done()throws RuntimeDaoException{
synchronized (listeners) {
for(final TableListener listener:listeners){
TRANSACTION_LISTENER.runDoneTask(new Runnable() {
@Override
public void run() {
try{
listener.done();
}catch(Exception e){
log("done listener %s error:%s",listener.getClass().getName(),e.getMessage());
if(BaseTableManager.isDebug()){
log(e);
}
}
}
});
}
}
}
/**
* determine if the container is empty.
* @return
*/
public boolean isEmpty() {
return listeners.isEmpty();
}
/**
* determine if the {@code listener} be added.
* @param listener
* @return {@code true} if {@code listener} exists in container
*/
public boolean contains(TableListener listener) {
synchronized (listeners) {
return listeners.contains(listener);
}
}
/**
* add {@code listener} into container
* @return {@code true} if add successfully.
*/
public boolean add(TableListener listener) {
synchronized (listeners) {
return null == listener ? false : listeners.add(listener);
}
}
/**
* remove {@code listener} from container
* @param listener instance that will be removed.
* @return {@code true} if remove successfully.
*/
public boolean remove(TableListener listener) {
synchronized (listeners) {
return null == listener? false : listeners.remove(listener);
}
}
/** remove all listeners in container */
public void clear() {
synchronized (listeners) {
listeners.clear();
}
}
private static class TransactionListenerImpl implements TransactionListener{
private static final ThreadLocal> commitTasks = new ThreadLocal<>();
private static final ThreadLocal> doneTasks = new ThreadLocal<>();
@Override
public void onBegin() {
commitTasks.set(new LinkedList());
doneTasks.set(new LinkedList());
}
private static void runEachTask(LinkedList tasks){
try {
// task.run()执行时可能会修改 tasks 的内容,如果直接对tasks遍历会导致 ConcurrentModificationException 异常
// 所以这里在tasks的复本(copy)上执行遍历
ImmutableList copy;
while (! tasks.isEmpty()) {
copy = ImmutableList.copyOf(tasks);
for (Runnable task : copy) {
task.run();
}
tasks.removeAll(copy);
}
} catch (Exception e) {
log("{}:{}",e.getClass().getName(),e.getMessage());
}
}
@Override
public void onCommit() {
// run all commit tasks
runEachTask(checkNotNull(commitTasks.get(),"'onBegin' must be called firstly"));
}
@Override
public void onEnd() {
// run all done tasks
runEachTask(checkNotNull(doneTasks.get(),"'onBegin' must be called firstly"));
commitTasks.remove();
doneTasks.remove();
}
void runCommitTask(Runnable task){
LinkedList tasks = commitTasks.get();
if(tasks != null){
tasks.add(task);
}else {
task.run();
}
}
void runDoneTask(Runnable task){
LinkedList tasks = doneTasks.get();
if(tasks != null){
tasks.add(task);
}else {
task.run();
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy