Index: topia2/src/java/org/codelutin/topia/framework/TopiaContextImpl.java diff -u topia2/src/java/org/codelutin/topia/framework/TopiaContextImpl.java:1.44 topia2/src/java/org/codelutin/topia/framework/TopiaContextImpl.java:1.45 --- topia2/src/java/org/codelutin/topia/framework/TopiaContextImpl.java:1.44 Tue Nov 14 22:37:02 2006 +++ topia2/src/java/org/codelutin/topia/framework/TopiaContextImpl.java Wed Nov 22 20:20:56 2006 @@ -23,9 +23,9 @@ * * @author poussin * - * @version $Revision: 1.44 $ + * @version $Revision: 1.45 $ * - * Last update: $Date: 2006/11/14 22:37:02 $ by : $Author: bpoussin $ + * Last update: $Date: 2006/11/22 20:20:56 $ by : $Author: bpoussin $ */ package org.codelutin.topia.framework; @@ -582,7 +582,7 @@ public TopiaContext beginTransaction() throws TopiaException { checkClosed("Ce contexte a ete ferme, impossible de commencer une transaction"); TopiaContextImpl result = new TopiaContextImpl(this); - getFiresSupport().fireOnPreCommit(result); + addChildContext(result); SessionFactory factory = getHibernateFactory(); result.hibernate = factory.openSession(); @@ -598,6 +598,7 @@ // de lock sur les tables. result.hibernate.beginTransaction(); + getFiresSupport().fireOnBeginTransaction(result); return result; } @@ -664,13 +665,13 @@ hibernate = getHibernateFactory().openSession(); hibernate.setFlushMode(FlushMode.NEVER); + hibernate.beginTransaction(); + getFiresSupport().fireOnPostRollback(this); TopiaContextImplementor parent = getParentContext(); if(parent != null) { parent.getFiresSupport().fireOnPostRollback(this); } - - hibernate.beginTransaction(); } catch (HibernateException eee) { throw new TopiaException(eee); Index: topia2/src/java/org/codelutin/topia/framework/TopiaFiresSupport.java diff -u topia2/src/java/org/codelutin/topia/framework/TopiaFiresSupport.java:1.4 topia2/src/java/org/codelutin/topia/framework/TopiaFiresSupport.java:1.5 --- topia2/src/java/org/codelutin/topia/framework/TopiaFiresSupport.java:1.4 Tue Nov 14 22:37:02 2006 +++ topia2/src/java/org/codelutin/topia/framework/TopiaFiresSupport.java Wed Nov 22 20:20:56 2006 @@ -26,8 +26,10 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; +import org.apache.commons.collections.map.IdentityMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.codelutin.topia.TopiaException; @@ -69,75 +71,145 @@ public class TopiaFiresSupport { static private Log log = LogFactory.getLog(TopiaFiresSupport.class); - static Object NO_CHANGE = new Object(); - - protected Set propertyChangeListeners = new HashSet(); + + /** used to fire read event */ + final static Object NO_CHANGE = new Object(); + /** used to collect entity modification during transaction */ + protected Map transactionEntities = new IdentityMap(); + protected Set propertyChangeListeners = new HashSet(); /* Pour la transaction */ protected ListenerSet transactionListeners = new ListenerSet(); protected ListenerSet transactionVetoables = new ListenerSet(); - protected TopiaTransactionEvent currentTransactionEvent; /* Pour les entités */ protected CategorisedListenerSet entityListeners = new CategorisedListenerSet(); protected CategorisedListenerSet entityVetoables = new CategorisedListenerSet(); + /** + * used to register objects loaded during transaction. + * @param entity + */ + public void warnOnLoadEntity(TopiaEntity entity) { + if (log.isDebugEnabled()) { + log.debug("warnOnReadEntity"); + } + EntityState state = transactionEntities.get(entity); + if (state == null) { + state = new EntityState(); + transactionEntities.put(entity, state); + } + state.addLoad(); + } + + /** + * used to register objects created during transaction. + * @param entity + */ + public void warnOnCreateEntity(TopiaEntity entity) { + if (log.isDebugEnabled()) { + log.debug("warnOnCreateEntity"); + } + EntityState state = transactionEntities.get(entity); + if (state == null) { + state = new EntityState(); + transactionEntities.put(entity, state); + } + state.addCreate(); + } + + /** + * used to register objects loaded during transaction. + * @param entity + */ + public void warnOnReadEntity(TopiaEntity entity) { + if (log.isDebugEnabled()) { + log.debug("warnOnReadEntity"); + } + // we don't create state if null, because state must be create + // before in warnOnLoad or warnOnCreate + EntityState state = transactionEntities.get(entity); + state.addRead(); + } + + /** + * used to register objects modified during transaction. + * @param entity + */ + public void warnOnUpdateEntity(TopiaEntity entity) { + if (log.isDebugEnabled()) { + log.debug("warnOnUpdateEntity"); + } + + // we don't create state if null, because state must be create + // before in warnOnLoad or warnOnCreate + EntityState state = transactionEntities.get(entity); + state.addUpdate(); + } + + /** + * used to register objects deleted during transaction. + * @param entity + */ + public void warnOnDeleteEntity(TopiaEntity entity) { + if (log.isDebugEnabled()) { + log.debug("warnOnDeleteEntity"); + } + // we don't create state if null, because state must be create + // before in warnOnLoad or warnOnCreate + EntityState state = transactionEntities.get(entity); + state.addDelete(); + } + /* Fires sur les transactions */ - public void fireOnPreCommit(TopiaContextImplementor context) { + public void fireOnBeginTransaction(TopiaContextImplementor context) { if (log.isDebugEnabled()) { - log.debug("fireOnPostCommit"); + log.debug("fireOnBeginTransaction"); } try { - context.getFiresSupport().currentTransactionEvent = new TopiaTransactionEvent(context); + TopiaTransactionEvent e = new TopiaTransactionEvent(context); for(Iterator l=transactionVetoables.iterator(); l.hasNext();) { - l.next().beginTransaction(context.getFiresSupport().currentTransactionEvent); + l.next().beginTransaction(e); } } catch (Exception eee) { throw new TopiaVetoException(eee); } } - public void fireOnEntity(TopiaEntity entity) { - if (log.isDebugEnabled()) { - log.debug("fireOnEntity"); - } - currentTransactionEvent.addEntity(entity); - } - public void fireOnPostCommit(TopiaContextImplementor context) { if (log.isDebugEnabled()) { log.debug("fireOnPostCommit"); } - try { - for(Iterator l=transactionListeners.iterator(); l.hasNext();) { - l.next().commit(currentTransactionEvent); - } - currentTransactionEvent = new TopiaTransactionEvent(context); - } catch (Exception eee) { - if (log.isErrorEnabled()) { - log.error("Can't fireOnPostCommit", eee); + TopiaTransactionEvent e = new TopiaTransactionEvent(context, transactionEntities); + for(Iterator l=transactionListeners.iterator(); l.hasNext();) { + try { + l.next().commit(e); + } catch (Exception eee) { + if (log.isErrorEnabled()) { + log.error("Can't fireOnPostCommit", eee); + } } - } + transactionEntities.clear(); } public void fireOnPostRollback(TopiaContextImplementor context) { if (log.isDebugEnabled()) { log.debug("fireOnPostRollback"); } - try { - for(Iterator l=transactionListeners.iterator(); l.hasNext();) { - l.next().rollback(currentTransactionEvent); - } - currentTransactionEvent = new TopiaTransactionEvent(context); - } catch (Exception eee) { - if (log.isErrorEnabled()) { - log.error("Can't fireOnPostRollback", eee); + TopiaTransactionEvent e = new TopiaTransactionEvent(context, transactionEntities); + for(Iterator l=transactionListeners.iterator(); l.hasNext();) { + try { + l.next().rollback(e); + } catch (Exception eee) { + if (log.isErrorEnabled()) { + log.error("Can't fireOnPostRollback", eee); + } } - } + transactionEntities.clear(); } /* Fires sur les entités */ @@ -145,13 +217,13 @@ if (log.isDebugEnabled()) { log.debug("fireOnPreCreate"); } - try { - TopiaEntityEvent event = new TopiaEntityEvent(context, entity, state); - for(Iterator l=entityVetoables.iterator(entity.getClass()); l.hasNext();) { + TopiaEntityEvent event = new TopiaEntityEvent(context, entity, state); + for(Iterator l=entityVetoables.iterator(entity.getClass()); l.hasNext();) { + try { l.next().create(event); + } catch (Exception eee) { + throw new TopiaVetoException(eee); } - } catch (Exception eee) { - throw new TopiaVetoException(eee); } } @@ -159,15 +231,15 @@ if (log.isDebugEnabled()) { log.debug("fireOnPostCreate"); } - try { - TopiaEntityEvent event = new TopiaEntityEvent(context, entity, state); - for(Iterator l=entityListeners.iterator(entity.getClass()); l.hasNext();) { + warnOnCreateEntity(entity); + TopiaEntityEvent event = new TopiaEntityEvent(context, entity, state); + for(Iterator l=entityListeners.iterator(entity.getClass()); l.hasNext();) { + try { l.next().create(event); - } - currentTransactionEvent.addEntity(entity); - } catch (Exception eee) { - if (log.isErrorEnabled()) { - log.error("Can't fireOnPostCreate for entity: " + entity, eee); + } catch (Exception eee) { + if (log.isErrorEnabled()) { + log.error("Can't fireOnPostCreate for entity: " + entity, eee); + } } } } @@ -176,13 +248,13 @@ if (log.isDebugEnabled()) { log.debug("fireOnPreLoad"); } - try { - TopiaEntityEvent event = new TopiaEntityEvent(context, entity, state); - for(Iterator l=entityVetoables.iterator(entity.getClass()); l.hasNext();) { + TopiaEntityEvent event = new TopiaEntityEvent(context, entity, state); + for(Iterator l=entityVetoables.iterator(entity.getClass()); l.hasNext();) { + try { l.next().load(event); + } catch (Exception eee) { + throw new TopiaVetoException(eee); } - } catch (Exception eee) { - throw new TopiaVetoException(eee); } } @@ -190,14 +262,15 @@ if (log.isDebugEnabled()) { log.debug("fireOnPostLoad"); } - try { - TopiaEntityEvent event = new TopiaEntityEvent(context, entity, state); - for(Iterator l=entityListeners.iterator(entity.getClass()); l.hasNext();) { + warnOnLoadEntity(entity); + TopiaEntityEvent event = new TopiaEntityEvent(context, entity, state); + for(Iterator l=entityListeners.iterator(entity.getClass()); l.hasNext();) { + try { l.next().load(event); - } - } catch (Exception eee) { - if (log.isErrorEnabled()) { - log.error("Can't fireOnPostLoad for entity: " + entity, eee); + } catch (Exception eee) { + if (log.isErrorEnabled()) { + log.error("Can't fireOnPostLoad for entity: " + entity, eee); + } } } } @@ -206,14 +279,13 @@ if (log.isDebugEnabled()) { log.debug("fireOnPreUpdate"); } - try { - TopiaEntityEvent event = new TopiaEntityEvent(context, entity, state); - for(Iterator l=entityVetoables.iterator(entity.getClass()); l.hasNext();) { + TopiaEntityEvent event = new TopiaEntityEvent(context, entity, state); + for(Iterator l=entityVetoables.iterator(entity.getClass()); l.hasNext();) { + try { l.next().update(event); + } catch (Exception eee) { + throw new TopiaVetoException(eee); } - currentTransactionEvent.addEntity(entity); - } catch (Exception eee) { - throw new TopiaVetoException(eee); } } @@ -221,14 +293,15 @@ if (log.isDebugEnabled()) { log.debug("fireOnPostUpdate"); } - try { - TopiaEntityEvent event = new TopiaEntityEvent(context, entity, state); - for(Iterator l=entityListeners.iterator(entity.getClass()); l.hasNext();) { + warnOnUpdateEntity(entity); + TopiaEntityEvent event = new TopiaEntityEvent(context, entity, state); + for(Iterator l=entityListeners.iterator(entity.getClass()); l.hasNext();) { + try { l.next().update(event); - } - } catch (Exception eee) { - if (log.isErrorEnabled()) { - log.error("Can't fireOnPostUpdate for entity: " + entity, eee); + } catch (Exception eee) { + if (log.isErrorEnabled()) { + log.error("Can't fireOnPostUpdate for entity: " + entity, eee); + } } } } @@ -237,13 +310,13 @@ if (log.isDebugEnabled()) { log.debug("fireOnPreDelete"); } - try { - TopiaEntityEvent event = new TopiaEntityEvent(context, entity, state); - for(Iterator l=entityVetoables.iterator(entity.getClass()); l.hasNext();) { + TopiaEntityEvent event = new TopiaEntityEvent(context, entity, state); + for(Iterator l=entityVetoables.iterator(entity.getClass()); l.hasNext();) { + try { l.next().delete(event); + } catch (Exception eee) { + throw new TopiaVetoException(eee); } - } catch (Exception eee) { - throw new TopiaVetoException(eee); } } @@ -251,15 +324,15 @@ if (log.isDebugEnabled()) { log.debug("fireOnPostDelete"); } - try { - TopiaEntityEvent event = new TopiaEntityEvent(context, entity, state); - for(Iterator l=entityListeners.iterator(entity.getClass()); l.hasNext();) { + warnOnDeleteEntity(entity); + TopiaEntityEvent event = new TopiaEntityEvent(context, entity, state); + for(Iterator l=entityListeners.iterator(entity.getClass()); l.hasNext();) { + try { l.next().delete(event); - } - currentTransactionEvent.addEntity(entity); - } catch (Exception eee) { - if (log.isErrorEnabled()) { - log.error("Can't fireOnPostDelete for entity: " + entity, eee); + } catch (Exception eee) { + if (log.isErrorEnabled()) { + log.error("Can't fireOnPostDelete for entity: " + entity, eee); + } } } } @@ -284,6 +357,7 @@ if (log.isDebugEnabled()) { log.debug("fireOnPostRead"); } + warnOnReadEntity(entity); try { listeners.firePropertyChange(propertyName, value, NO_CHANGE); } catch (Exception eee) { @@ -300,6 +374,7 @@ if (log.isDebugEnabled()) { log.debug("fireOnPostRead"); } + warnOnReadEntity(entity); try { listeners.fireIndexedPropertyChange(propertyName, index, value, NO_CHANGE); } catch (Exception eee) { @@ -329,18 +404,24 @@ if (log.isDebugEnabled()) { log.debug("fireOnPostWrite"); } - try { - if (propertyChangeListeners.size() > 0) { - PropertyChangeEvent e = new PropertyChangeEvent(entity, propertyName, oldValue, newValue); - for (PropertyChangeListener l : propertyChangeListeners) { + warnOnUpdateEntity(entity); + if (propertyChangeListeners.size() > 0) { + PropertyChangeEvent e = new PropertyChangeEvent(entity, propertyName, oldValue, newValue); + for (PropertyChangeListener l : propertyChangeListeners) { + try { l.propertyChange(e); + } catch (Exception eee) { + if (log.isErrorEnabled()) { + log.error("Can't fire property change for: " + propertyName, eee); + } } } + } + try { listeners.firePropertyChange(propertyName, oldValue, newValue); - currentTransactionEvent.addEntity(entity); } catch (Exception eee) { if (log.isErrorEnabled()) { - log.error("Can't fireOnPostWrite", eee); + log.error("Can't fireOnPostWrite: " + propertyName, eee); } } } @@ -351,9 +432,9 @@ if (log.isDebugEnabled()) { log.debug("fireOnPostWrite"); } + warnOnUpdateEntity(entity); try { listeners.fireIndexedPropertyChange(propertyName, index, oldValue, newValue); - currentTransactionEvent.addEntity(entity); } catch (Exception eee) { if (log.isErrorEnabled()) { log.error("Can't fireOnPostWrite", eee); Index: topia2/src/java/org/codelutin/topia/framework/EntityState.java diff -u /dev/null topia2/src/java/org/codelutin/topia/framework/EntityState.java:1.1 --- /dev/null Wed Nov 22 20:21:02 2006 +++ topia2/src/java/org/codelutin/topia/framework/EntityState.java Wed Nov 22 20:20:56 2006 @@ -0,0 +1,81 @@ +/* *##% + * Copyright (C) 2006 + * Code Lutin, Cédric Pineau, Benjamin Poussin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +/* * + * EntityState.java + * + * Created: 22 nov. 06 12:10:57 + * + * @author poussin + * @version $Revision: 1.1 $ + * + * Last update: $Date: 2006/11/22 20:20:56 $ + * by : $Author: bpoussin $ + */ + +package org.codelutin.topia.framework; + + +/** + * Used to know the state of entity during transaction + * + * @author poussin + */ +public class EntityState { + + final static int LOAD = 0; + final static int READ = 1; + final static int CREATE = 2; + final static int UPDATE = 4; + final static int DELETE = 8; + + protected int state = 0; + + public void addLoad(){} + public void addRead(){ + state |= READ; + } + public void addCreate(){ + state |= CREATE; + } + public void addUpdate(){ + state |= UPDATE; + } + public void addDelete(){ + state |= DELETE; + } + + public boolean isLoad() { + return (state & LOAD) == LOAD; + } + public boolean isRead() { + return (state & READ) == READ; + } + public boolean isCreate() { + return (state & CREATE) == CREATE; + } + public boolean isUpdate() { + return (state & UPDATE) == UPDATE; + } + public boolean isDelete() { + return (state & DELETE) == DELETE; + } +} + +