Index: topia/src/java/org/codelutin/topia/persistence/PersistenceHelper.java diff -u topia/src/java/org/codelutin/topia/persistence/PersistenceHelper.java:1.9 topia/src/java/org/codelutin/topia/persistence/PersistenceHelper.java:1.10 --- topia/src/java/org/codelutin/topia/persistence/PersistenceHelper.java:1.9 Tue Jul 19 13:15:13 2005 +++ topia/src/java/org/codelutin/topia/persistence/PersistenceHelper.java Wed Jul 20 12:49:52 2005 @@ -23,20 +23,20 @@ * Created: Aug 1, 2004 * * @author Cédric Pineau - * @version $Revision: 1.9 $ + * @version $Revision: 1.10 $ * - * Last update : $Date: 2005/07/19 13:15:13 $ + * Last update : $Date: 2005/07/20 12:49:52 $ * by : $Author: bpoussin $ */ package org.codelutin.topia.persistence; import java.util.List; - -import org.codelutin.topia.AsynchronousLoader; +import org.codelutin.topia.TopiaContext; import org.codelutin.topia.TopiaEntity; import org.codelutin.topia.TopiaException; import org.codelutin.topia.TopiaQuery; +import org.codelutin.topia.AsynchronousLoader; /** * @@ -46,6 +46,11 @@ public TopiaContext getContext(); /** + * Force le chargement des données de l'objet si besoin + */ + public void load(TopiaEntity o) throws TopiaException; + + /** * Permet de creer une nouvelle entité */ public A create(Class entityClass) throws TopiaException; @@ -56,6 +61,10 @@ * cette méthode après un create. * Après l'appel de cette méthode, il ne faut plus utilisé l'entité passé * en paramètre, mais celle retournée. + *

+ * Cette methode permet aussi de recuperer un objet qui aurait ete supprimé + * avec un appel à delete, cela ne fonctionne que si ca ete fait dans la + * meme transaction */ public A makePersistent(A entity) throws TopiaException; @@ -81,6 +90,14 @@ public int size(TopiaQuery query) throws TopiaException; /** + * Permet de récupéré de manière asynchrone une liste d'objet par rapport + * a une requete. + * @param query la requete a executer + * @return a AsynchronousLoader + */ + public AsynchronousLoader findAsynchronously(TopiaQuery query) throws TopiaException; + + /** * Charge le XML passé en paramètre dans la base * @param xml une chaine XML */ @@ -107,11 +124,11 @@ * Commit les changements fait durant la transaction * @throws TopiaException si aucune transaction ouverte pour le thread courant */ - public void commitTransaction() throws TopiaException; + public TopiaTransaction commitTransaction() throws TopiaException; /** * Rollback les changements fait durant la transaction * @throws TopiaException si aucune transaction ouverte pour le thread courant */ - public void rollbackTransaction() throws TopiaException; + public TopiaTransaction rollbackTransaction() throws TopiaException; } Index: topia/src/java/org/codelutin/topia/persistence/PersistenceStorage.java diff -u topia/src/java/org/codelutin/topia/persistence/PersistenceStorage.java:1.1 topia/src/java/org/codelutin/topia/persistence/PersistenceStorage.java:1.2 --- topia/src/java/org/codelutin/topia/persistence/PersistenceStorage.java:1.1 Tue Jul 19 13:15:13 2005 +++ topia/src/java/org/codelutin/topia/persistence/PersistenceStorage.java Wed Jul 20 12:49:52 2005 @@ -23,14 +23,16 @@ * Created: 16 juillet 2005 23:40:21 CEST * * @author Benjamin POUSSIN - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ * - * Last update: $Date: 2005/07/19 13:15:13 $ + * Last update: $Date: 2005/07/20 12:49:52 $ * by : $Author: bpoussin $ */ package org.codelutin.topia.persistence; +import java.util.Collection; +import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import java.util.Properties; Index: topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceCache.java diff -u topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceCache.java:1.1 topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceCache.java:1.2 --- topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceCache.java:1.1 Tue Jul 19 13:15:13 2005 +++ topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceCache.java Wed Jul 20 12:49:52 2005 @@ -23,9 +23,9 @@ * Created: 16 juillet 2005 23:42:14 CEST * * @author Benjamin POUSSIN - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ * - * Last update: $Date: 2005/07/19 13:15:13 $ + * Last update: $Date: 2005/07/20 12:49:52 $ * by : $Author: bpoussin $ */ @@ -37,6 +37,15 @@ import java.util.Properties; import org.codelutin.topia.TopiaEntity; +/** +* Cache utiliser dans l'implantation par defaut du PersistenceHelper. +* Il conserve une entity dans un SoftReference. +* Potentiellement, on peut modifier l'implantation du cache a condition de +* faire une classe qui herite de cette implantation, pour cela il faut +* mettre dans le fichier de propriété du PersistenceHelper la classe a utiliser +* dans la propriété: persistence.cache.class +* @todo mettre en soft reference +*/ public class TopiaPersistenceCache { // TopiaPersistenceCache /** to use log facility, just put in your code: log.info(\"...\"); */ Index: topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceHelper.java diff -u topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceHelper.java:1.1 topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceHelper.java:1.2 --- topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceHelper.java:1.1 Tue Jul 19 13:15:13 2005 +++ topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceHelper.java Wed Jul 20 12:49:52 2005 @@ -23,20 +23,31 @@ * Created: Jul 16, 2005 * * @author Benjamin POUSSIN - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ * - * Last update : $Date: 2005/07/19 13:15:13 $ + * Last update : $Date: 2005/07/20 12:49:52 $ * by : $Author: bpoussin $ */ package org.codelutin.topia.persistence; +import java.io.IOException; import java.lang.IllegalStateException; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; import java.util.Properties; +import org.codelutin.querycollection.CollectionQueryHelper; +import org.codelutin.queryparser.QueryHelperException; +import org.codelutin.topia.AsynchronousLoader; import org.codelutin.topia.TopiaConst; import org.codelutin.topia.TopiaContext; import org.codelutin.topia.TopiaEntity; import org.codelutin.topia.TopiaException; +import org.codelutin.topia.TopiaId; +import org.codelutin.topia.TopiaNotFoundException; +import org.codelutin.topia.TopiaQuery; public class TopiaPersistenceHelper implements PersistenceHelper { // TopiaPersistenceHelper @@ -44,7 +55,7 @@ * Le context a partir duquel on a recupere ce AbstractPersistenceHelper */ protected TopiaContext context = null; - protected TopiaPersistenceCache = null; + protected TopiaPersistenceCache cache = null; protected PersistenceStorage storage = null; /** @@ -68,17 +79,17 @@ this.properties = properties; } - protected PersistenceStorage getStorage(){ + protected PersistenceStorage getStorage() throws TopiaNotFoundException { if(storage == null){ - storage = getContext().getContextHelper().getHelper(getProperties(), + storage = (PersistenceStorage)getContext().getContextHelper().getHelper(getProperties(), TopiaConst.PERSISTENCE_STORAGE_CLASS, true); } return storage; } - protected TopiaPersistenceCache getCache(){ + protected TopiaPersistenceCache getCache() throws TopiaNotFoundException { if(cache == null){ - cache = getContext().getContextHelper().getHelper(getProperties(), + cache = (TopiaPersistenceCache)getContext().getContextHelper().getHelper(getProperties(), TopiaConst.PERSISTENCE_CACHE_CLASS, false); } return cache; @@ -88,43 +99,140 @@ getStorage().beginTransaction(getContext().getTransaction()); } - public void commitTransaction() throws TopiaException { - getStorage().commitTransaction(getContext().getTransaction()); + public TopiaTransaction commitTransaction() throws TopiaException { + return getStorage().commitTransaction(getContext().getTransaction()); } - public void rollbackTransaction() throws TopiaException { - getStorage().rollbackTransaction(getContext().getTransaction()); + public TopiaTransaction rollbackTransaction() throws TopiaException { + return getStorage().rollbackTransaction(getContext().getTransaction()); + } + + /** + * Recupere la version de schema par introspection sur les MetaInfos + */ + protected long getSchemaVersion(Class entityClass){ + // TODO implanter getSchemaVersion + return 0; } public A create(Class entityClass) throws TopiaException { - // FIXME creer un nouveau proxy + String id = TopiaId.create(entityClass); + + TopiaPersistenceObject tpo = new TopiaPersistenceObject(id); + tpo.getManagement().setDate(getContext().getTransaction().getId()); + tpo.getManagement().setSchemaVersion(getSchemaVersion(entityClass)); + tpo.getManagement().setNew(true); + + A result = TopiaPersistenceProxy.newProxy(this, entityClass, tpo); + getCache().put(id, result); + + return result; } public A makePersistent(A entity) throws TopiaException { - // TODO créer un nouveau proxy a partir des informations de l'entité - // passée en parametre et retourner le proxy. - return entity; + A result = entity; + if(entity == null){ + throw new IllegalArgumentException("Null is not a valid entity"); + } + if(!Proxy.isProxyClass(entity.getClass())){ + if(getStorage().exists(getContext().getTransaction(), entity.get_topiaId_())){ + throw new IllegalArgumentException("This entity allready exists in Storage."); + } + result = (A)create(entity.getEntityClass()); + } + TopiaPersistenceProxy tpp = + (TopiaPersistenceProxy)Proxy.getInvocationHandler(result); + TopiaPersistenceObject tpo = tpp.getObject(); + + if(tpp.getPersistenceHelper() != this){ + if(getStorage().exists(getContext().getTransaction(), entity.get_topiaId_())){ + throw new IllegalArgumentException("This entity allready exists in Storage."); + } + // l'objet venait d'un autre PersistenceHelper, il faut en recreer + // un pour nous + tpo = tpo.clone(); + tpo.getManagement().setNew(true); + tpo.getManagement().setStored(false); + } + + // si jamais on vient de creer l'entity a partir d'une entity non proxy + // il faut remettre le meme id + tpo.getManagement().setId(entity.get_topiaId_()); + // l'objet n'est plus supprimé s'il l'etait + tpo.getManagement().setDelete(false); + + getStorage().store(getContext().getTransaction(), tpo); + return result; } public A update(A entity) throws TopiaException{ - // FIXME recuperer l'objet encapsulé dans le proxy et faire un store - // getStorage().store(getContext().getTransaction(), entity); + if(entity == null){ + throw new IllegalArgumentException("Null is not a valid entity"); + } + if(!Proxy.isProxyClass(entity.getClass())){ + throw new IllegalArgumentException("Only proxy is svalid entity"); + } + + TopiaPersistenceProxy tpp = + (TopiaPersistenceProxy)Proxy.getInvocationHandler(entity); + + if(tpp.getPersistenceHelper() != this){ + throw new IllegalArgumentException("This entity is not attached to this PersistenceHelper, you must call makePersistent first"); + } + + TopiaPersistenceObject tpo = tpp.getObject(); + if(tpo.getManagement().isDeleted()){ + throw new IllegalArgumentException("This entity is deleted, you can't update it. You must call makePersistent first"); + } + + getStorage().store(getContext().getTransaction(), tpo); return entity; } public void delete(TopiaEntity entity) throws TopiaException { - // FIXME, recuperer l'objet encapsulé dans le proxy et le marquer - // supprimé. - // appeler le store + if(entity == null){ + throw new IllegalArgumentException("Null is not a valid entity"); + } + if(!Proxy.isProxyClass(entity.getClass())){ + throw new IllegalArgumentException("Only proxy is svalid entity"); + } + + TopiaPersistenceProxy tpp = + (TopiaPersistenceProxy)Proxy.getInvocationHandler(entity); + + if(tpp.getPersistenceHelper() != this){ + throw new IllegalArgumentException("This entity is not attached to this PersistenceHelper, you must call makePersistent first"); + } + + TopiaPersistenceObject tpo = tpp.getObject(); + tpo.getManagement().setDelete(true); + getStorage().store(getContext().getTransaction(), tpo); } public List find(TopiaQuery query) throws TopiaException { - List result = null; + List result = new ArrayList(); if(getStorage().haveFindImplemented()){ - result = new TopiaPersistenceLazyList(this, getStorage().find(query)); + for(String id: getStorage().find(getContext().getTransaction(), query)) { + result.add(findByTopiaId(id)); + } } else { - // TODO faire la recherche - // getStorage().getAllId(); + List entities = new ArrayList(); + for(String id: getStorage().getAllId(getContext().getTransaction())){ + if(TopiaId.getClassNameAsString(id).equals(query.getFrom())){ + entities.add(findByTopiaId(id)); + } + } + + CollectionQueryHelper queryHelper = new CollectionQueryHelper(entities); + try { + queryHelper.setQuery(query.getQueryString()); + queryHelper.addArgs(query.getArgs()); + result.addAll((Collection)queryHelper.execute()); + } catch (IOException eee) { + throw new TopiaException("Erreur durant le parsage de la requete: " + query, eee); + } catch (QueryHelperException eee) { + throw new TopiaException("Erreur durant l'execution de la requete" + query, eee); + } } return result; } @@ -132,13 +240,19 @@ public int size(TopiaQuery query) throws TopiaException { List result = null; if(getStorage().haveFindImplemented()){ - result = getStorage().find(query)); + result = getStorage().find(getContext().getTransaction(), query); } else { result = find(query); } return result.size(); } + public AsynchronousLoader findAsynchronously(TopiaQuery query) throws TopiaException { + // TODO + throw new UnsupportedOperationException("TODO"); + } + + public void importXML(String xml) throws TopiaException { // TODO throw new UnsupportedOperationException(); @@ -150,7 +264,41 @@ } public TopiaEntity findByTopiaId(String id) throws TopiaException { - // FIXME + if(!getStorage().exists(getContext().getTransaction(), id)){ + throw new TopiaException("This id don't exist in Storage: " + id); + } + TopiaEntity result = getCache().get(id); + if(result == null){ + Class entityClass = TopiaId.getClassName(id); + TopiaPersistenceObject tpo = new TopiaPersistenceObject(id); + tpo.getManagement().setDate(getContext().getTransaction().getId()); + result = TopiaPersistenceProxy.newProxy(this, entityClass, tpo); + getCache().put(id, result); + } + return result; + } + + public void load(TopiaEntity entity) throws TopiaException { + if(entity == null){ + throw new IllegalArgumentException("Null is not a valid entity"); + } + if(!Proxy.isProxyClass(entity.getClass())){ + throw new IllegalArgumentException("Only proxy is svalid entity"); + } + + TopiaPersistenceProxy tpp = + (TopiaPersistenceProxy)Proxy.getInvocationHandler(entity); + + if(tpp.getPersistenceHelper() != this){ + throw new IllegalArgumentException("This entity is not attached to this PersistenceHelper, you must call makePersistent first"); + } + + TopiaPersistenceObject tpo = tpp.getObject(); + if(tpo.getManagement().isDeleted()){ + throw new IllegalArgumentException("This entity is deleted, you can't load it. You must call makePersistent first"); + } + + getStorage().restore(getContext().getTransaction(), tpo); } } // TopiaPersistenceHelper Index: topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceObject.java diff -u topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceObject.java:1.1 topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceObject.java:1.2 --- topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceObject.java:1.1 Tue Jul 19 13:15:13 2005 +++ topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceObject.java Wed Jul 20 12:49:52 2005 @@ -23,30 +23,45 @@ * Created: 16 juillet 2005 23:44:18 CEST * * @author Benjamin POUSSIN - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ * - * Last update: $Date: 2005/07/19 13:15:13 $ + * Last update: $Date: 2005/07/20 12:49:52 $ * by : $Author: bpoussin $ */ package org.codelutin.topia.persistence; import java.io.Serializable; +import java.lang.Cloneable; import java.util.HashSet; import java.util.logging.Level; import java.util.logging.Logger; import java.util.Set; -public class TopiaPersistenceObject implements Serializable { // TopiaPersistenceObject +public class TopiaPersistenceObject implements Serializable, Cloneable { // TopiaPersistenceObject /** to use log facility, just put in your code: log.info(\"...\"); */ static private Logger log = Logger.getLogger("org.codelutin.topia.persistence.TopiaPersistenceObject"); protected TopiaPersistenceObjectData data = null; protected TopiaPersistenceObjectManagementData management = null; - protected Set modifiedFields = new HashSet; + protected Set modifiedFields = new HashSet(); + protected Set askedFields = new HashSet(); - public TopiaPersistenceObject(){} + public TopiaPersistenceObject(String id){ + management = new TopiaPersistenceObjectManagementData(id); + data = new TopiaPersistenceObjectData(); + } + + public TopiaPersistenceObject clone(){ + TopiaPersistenceObject result = new TopiaPersistenceObject(getId()); + result.getManagement().state = getManagement().state.clone(); + result.getManagement().setDate(getManagement().getDate()); + result.getManagement().setSchemaVersion(getManagement().getSchemaVersion()); + result.getData().putAll(getData()); + + return result; + } public TopiaPersistenceObjectData getData(){ return data; @@ -60,6 +75,10 @@ return modifiedFields; } + public Set getAskedFields(){ + return askedFields; + } + /** * 2 objet sont egaux si leur id sont egaux et qu'ils ont la meme date */ @@ -80,11 +99,19 @@ } public Object getField(String fieldName){ - return getData().getField(fieldName); + Object result = getData().getField(fieldName); + if(result == data.UNLOADED){ + askedFields.add(fieldName); + } + return result; } public void setField(String fieldName, Object value){ getData().setField(fieldName, value); + // on vient de modifier le champs donc s'il etait demandé ce n'est plus + // la peine de le recuperer + modifiedFields.add(fieldName); + askedFields.remove(fieldName); } } // TopiaPersistenceObject Index: topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceObjectData.java diff -u topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceObjectData.java:1.1 topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceObjectData.java:1.2 --- topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceObjectData.java:1.1 Tue Jul 19 13:15:13 2005 +++ topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceObjectData.java Wed Jul 20 12:49:52 2005 @@ -23,9 +23,9 @@ * Created: 16 juillet 2005 23:45:07 CEST * * @author Benjamin POUSSIN - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ * - * Last update: $Date: 2005/07/19 13:15:13 $ + * Last update: $Date: 2005/07/20 12:49:52 $ * by : $Author: bpoussin $ */ @@ -40,7 +40,24 @@ /** to use log facility, just put in your code: log.info(\"...\"); */ static private Logger log = Logger.getLogger("org.codelutin.topia.persistence.TopiaPersistenceObjectData"); + static final Object UNLOADED = new Object(); + public TopiaPersistenceObjectData(){} + + public Object getField(String fieldName){ + Object result = UNLOADED; + if(containsKey(fieldName)){ + result = super.get(fieldName); + } + return result; + } + + public Object setField(String fieldName, Object value){ + if(value == UNLOADED){ + throw new IllegalArgumentException("La variable UNLOADED ne peut pas être affectée à un champs"); + } + return put(fieldName, value); + } } // TopiaPersistenceObjectData Index: topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceObjectManagementData.java diff -u topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceObjectManagementData.java:1.1 topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceObjectManagementData.java:1.2 --- topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceObjectManagementData.java:1.1 Tue Jul 19 13:15:13 2005 +++ topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceObjectManagementData.java Wed Jul 20 12:49:52 2005 @@ -23,24 +23,40 @@ * Created: 16 juillet 2005 23:46:51 CEST * * @author Benjamin POUSSIN - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ * - * Last update: $Date: 2005/07/19 13:15:13 $ + * Last update: $Date: 2005/07/20 12:49:52 $ * by : $Author: bpoussin $ */ package org.codelutin.topia.persistence; import java.io.Serializable; +import java.util.EnumSet; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.Set; public class TopiaPersistenceObjectManagementData implements Serializable { // TopiaPersistenceObjectManagementData /** to use log facility, just put in your code: log.info(\"...\"); */ static private Logger log = Logger.getLogger("org.codelutin.topia.persistence.TopiaPersistenceObjectManagementData"); + static enum State { + /** l'objet est marque comme supprime */ + DELETED, + /** l'objet vient d'etre creer mais n'a jamais ete sauvé */ + NEW, + /** l'objet a deja ete sauvé */ + STORED; + } + protected String id = null; + protected EnumSet state = EnumSet.noneOf(State.class); + protected long date = 0; + protected long schemaVersion = 0; + + public TopiaPersistenceObjectManagementData(){} public TopiaPersistenceObjectManagementData(String id){ this.id = id; @@ -49,12 +65,60 @@ public String getId(){ return id; } - public boolean isNew(){} - public boolean isDeleted(){} - public boolean isStored(){} - public boolean Unloaded(){} - public long getDate(){} - public long getSchemaVersion(){} + public void setId(String id){ + this.id = id; + } + + public boolean isNew(){ + return state.contains(State.NEW); + } + public void setNew(boolean v){ + if(v){ + state.add(State.NEW); + } else { + state.remove(State.NEW); + } + } + + public boolean isDeleted(){ + return state.contains(State.DELETED); + } + public void setDelete(boolean v){ + if(v){ + state.add(State.DELETED); + } else { + state.remove(State.DELETED); + } + } + + public boolean isStored(){ + return state.contains(State.STORED); + } + public void setStored(boolean v){ + if(v){ + state.add(State.STORED); + } else { + state.remove(State.STORED); + } + } + + public boolean Unloaded(){ + return state.isEmpty(); + } + + public long getDate(){ + return date; + } + public void setDate(long date){ + this.date = date; + } + + public long getSchemaVersion(){ + return schemaVersion; + } + public void setSchemaVersion(long schemaVersion){ + this.schemaVersion = schemaVersion; + } } // TopiaPersistenceObjectManagementData Index: topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceProxy.java diff -u topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceProxy.java:1.1 topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceProxy.java:1.2 --- topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceProxy.java:1.1 Tue Jul 19 13:15:13 2005 +++ topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceProxy.java Wed Jul 20 12:49:52 2005 @@ -23,9 +23,9 @@ * Created: 16 juillet 2005 23:52:35 CEST * * @author Benjamin POUSSIN -* @version $Revision: 1.1 $ +* @version $Revision: 1.2 $ * -* Last update: $Date: 2005/07/19 13:15:13 $ +* Last update: $Date: 2005/07/20 12:49:52 $ * by : $Author: bpoussin $ */ @@ -34,11 +34,18 @@ import java.io.Serializable; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Arrays; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.beanutils.MethodUtils; import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.lang.StringUtils; +import org.codelutin.topia.EntitiesHelper; +import org.codelutin.topia.TopiaEntity; import org.codelutin.topia.TopiaEntityOperation; +import org.codelutin.topia.TopiaException; +import org.codelutin.topia.TopiaId; import org.codelutin.util.ArrayUtil; public class TopiaPersistenceProxy implements InvocationHandler { // TopiaPersistenceProxy @@ -46,10 +53,9 @@ /** to use log facility, just put in your code: log.info(\"...\"); */ static private Logger log = Logger.getLogger("org.codelutin.topia.persistence.TopiaPersistenceProxy"); - static public TopiaEntity newProxy(PersistenceHelper ph, TopiaPersistenceObject o) throws TopiaException { - Class clazz = TopiaId.getClassName(o.getId()); - TopiaEntity result = (TopiaEntity) Proxy.newProxyInstance(TopiaPersistenceProxy.class.getClassLoader(), - new Class[] { clazz }, new TopiaPersistenceProxy(ph, o)); + static public A newProxy(PersistenceHelper ph, Class clazz, TopiaPersistenceObject o) throws TopiaException { + A result = (A) Proxy.newProxyInstance(TopiaPersistenceProxy.class.getClassLoader(), + new Class[] { clazz }, new TopiaPersistenceProxy(ph, clazz, o)); return result; } @@ -57,8 +63,8 @@ protected Class interfacez = null; protected TopiaPersistenceObject o = null; - protected TopiaPersistenceProxy(PersistenceHelper tph, Class interfacez, TopiaPersistenceObject o){ - this.tph = tph; + protected TopiaPersistenceProxy(PersistenceHelper ph, Class interfacez, TopiaPersistenceObject o){ + this.ph = ph; this.interfacez = interfacez; this.o = o; } @@ -67,31 +73,36 @@ return o; } + public PersistenceHelper getPersistenceHelper(){ + return ph; + } + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + TopiaEntity entity = (TopiaEntity)proxy; String methodName = method.getName(); TopiaEntityOperation op = ph.getContext().getEntityOperation(interfacez); - Class [] argsType = ArrayUtil.concat([interfacez], + Class [] argsType = (Class[])ArrayUtil.concat(new Class[]{interfacez}, method.getParameterTypes()); Method m = MethodUtils.getAccessibleMethod(op.getClass(), methodName, argsType); if(m != null){ // on a retrouvé la méthode sur les operations, on peut donc l'appeler - Object [] argsObject = ArrayUtil.concat([o], args); + Object [] argsObject = ArrayUtil.concat(new Object[]{o}, args); return m.invoke(op, argsObject); } else { if(methodName.equals("toString") && method.getParameterTypes().length == 0){ EntitiesHelper entitiesHelper = ph.getContext().getEntitiesHelper(); Class entitiesHelperClass = entitiesHelper.getClass(); - Method m = MethodUtils.getAccessibleMethod(entitiesHelperClass, "toString", interfacez); + Method toString = MethodUtils.getAccessibleMethod(entitiesHelperClass, "toString", interfacez); if(m != null){ // on essai d'invoker la methode exact si possible - return m.invoke(entitiesHelper, this); + return toString.invoke(entitiesHelper, entity); } else { return MethodUtils.invokeMethod( - ph.getContext().getEntitiesHelper(), "toString", this); + ph.getContext().getEntitiesHelper(), "toString", entity); } }else if(methodName.equals("hashCode") && method.getParameterTypes().length == 0){ @@ -99,13 +110,13 @@ } else if(methodName.equals("equals") && method.getParameterTypes().length == 1){ if(args[0] instanceof TopiaEntity){ - TopiaEntity entity = (TopiaEntity)args[0]; - if(Proxy.isProxyClass(args[0].getClass())){ - TopiaPersistenceProxy tpp = (TopiaPersistenceProxy)Proxy.getInvocationHandler(entity); + TopiaEntity e = (TopiaEntity)args[0]; + if(Proxy.isProxyClass(e.getClass())){ + TopiaPersistenceProxy tpp = (TopiaPersistenceProxy)Proxy.getInvocationHandler(e); TopiaPersistenceObject obis = tpp.getObject(); return o.equals(obis); } else { - return o.getId().equals(entity.get_topiaId_()); + return o.getId().equals(e.get_topiaId_()); } } else { return Boolean.FALSE; @@ -116,11 +127,11 @@ }else if(methodName.startsWith("get") || methodName.startsWith("is")){ int prefix = methodName.startsWith("get")?3:2; String fieldName = - StringUtil.uncapitalize(methodName.substring(prefix)); + StringUtils.uncapitalize(methodName.substring(prefix)); Object result = o.getField(fieldName); - if(result == o.UNLOADED_FIELD){ - if(o.isNew()){ + if(result == o.getData().UNLOADED){ + if(o.getManagement().isNew()){ // TODO retourner la valeur par defaut defini dans le meta // si pas de valeur par defaut dans le meta, on retourne @@ -128,19 +139,20 @@ Class returnType = method.getReturnType(); result = getDefaultValue(returnType); } else { - tph.getStorage().restore(o); + ph.load(entity); result = o.getField(fieldName); } } + // FIXME a revoir avec les classes d'associations if(result instanceof String && TopiaId.isValidId((String)result)){ // TODO peut-etre verifier que l'objet pointer par l'id // existe reelement et si ce n'est pas le cas, mettre // a null le result et afficher un message WARNING - result = tph.findByTopiaId((String)result); + result = ph.findByTopiaId((String)result); } return result; } else if(methodName.startsWith("set")){ - String fieldName = StringUtil.uncapitalize(methodName.substring(3)); + String fieldName = StringUtils.uncapitalize(methodName.substring(3)); Object value = args[0]; if(value instanceof TopiaEntity){ value = ((TopiaEntity)value).get_topiaId_(); @@ -149,32 +161,30 @@ // on vient de modifier au moins un champs donc l'objet doit // rentrer dans la transaction o.getManagement().setDate(ph.getContext().getTransaction().getId()); - o.getModifiedFields().add(fieldName); - } else{ - log.severe("Can't find called method: " + method + " methodName: " + method.getName() + " methodArgType: " + Arrays.toString(method.getParameterTypes())); - // FIXME gérer les appels de méthode spécifique d'attribut (add, remove, ...) } - } + log.severe("Can't find called method: " + method + " methodName: " + method.getName() + " methodArgType: " + Arrays.toString(method.getParameterTypes())); + // FIXME gérer les appels de méthode spécifique d'attribut (add, remove, ...) + throw new UnsupportedOperationException("This proxy don't support this operation: " + method); } protected Object getDefaultValue(Class type){ Object result = null; - if(returnType.equals(Boolean.TYPE)){ + if(type.equals(Boolean.TYPE)){ result = Boolean.FALSE; - } else if(returnType.equals(Character.TYPE)){ + } else if(type.equals(Character.TYPE)){ result = Character.valueOf(Character.MIN_VALUE); - } else if(returnType.equals(Byte.TYPE)){ + } else if(type.equals(Byte.TYPE)){ result = Byte.valueOf((byte)0); - } else if(returnType.equals(Short.TYPE)){ + } else if(type.equals(Short.TYPE)){ result = Short.valueOf((short)0); - } else if(returnType.equals(Integer.TYPE)){ + } else if(type.equals(Integer.TYPE)){ result = Integer.valueOf(0); - } else if(returnType.equals(Long.TYPE)){ + } else if(type.equals(Long.TYPE)){ result = Long.valueOf(0); - } else if(returnType.equals(Float.TYPE)){ + } else if(type.equals(Float.TYPE)){ result = Float.valueOf(0); - } else if(returnType.equals(Double.TYPE)){ + } else if(type.equals(Double.TYPE)){ result = Double.valueOf(0); } return result; Index: topia/src/java/org/codelutin/topia/persistence/TopiaTransaction.java diff -u topia/src/java/org/codelutin/topia/persistence/TopiaTransaction.java:1.1 topia/src/java/org/codelutin/topia/persistence/TopiaTransaction.java:1.2 --- topia/src/java/org/codelutin/topia/persistence/TopiaTransaction.java:1.1 Tue Jul 19 13:15:13 2005 +++ topia/src/java/org/codelutin/topia/persistence/TopiaTransaction.java Wed Jul 20 12:49:52 2005 @@ -23,9 +23,9 @@ * Created: 16 juillet 2005 22:54:16 CEST * * @author Benjamin POUSSIN - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ * - * Last update: $Date: 2005/07/19 13:15:13 $ + * Last update: $Date: 2005/07/20 12:49:52 $ * by : $Author: bpoussin $ */ @@ -79,7 +79,7 @@ public TopiaTransaction regenerateTransaction(){ TopiaTransaction result = null; if(getParent() == null){ - result = tth.newTopiaTranstaction(); + result = tth.newTranstaction(); } else { getParent().getChilds().remove(this); result = getParent().newSubTransaction(); Index: topia/src/java/org/codelutin/topia/persistence/TopiaTransactionHelper.java diff -u topia/src/java/org/codelutin/topia/persistence/TopiaTransactionHelper.java:1.1 topia/src/java/org/codelutin/topia/persistence/TopiaTransactionHelper.java:1.2 --- topia/src/java/org/codelutin/topia/persistence/TopiaTransactionHelper.java:1.1 Tue Jul 19 13:15:13 2005 +++ topia/src/java/org/codelutin/topia/persistence/TopiaTransactionHelper.java Wed Jul 20 12:49:52 2005 @@ -23,9 +23,9 @@ * Created: 16 juillet 2005 23:27:18 CEST * * @author Benjamin POUSSIN - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ * - * Last update: $Date: 2005/07/19 13:15:13 $ + * Last update: $Date: 2005/07/20 12:49:52 $ * by : $Author: bpoussin $ */ @@ -61,7 +61,7 @@ * Utilisé aussi pour les dates de modif des objets qui doivent * aussi etre unique pour le meme id */ - public synchronized long getDate(){ + public synchronized long getUniqueDate(){ long result = System.currentTimeMillis(); // la derniere date retourné doit toujours etre unique // et superieur a la precedente en valeur absolue Index: topia/src/java/org/codelutin/topia/persistence/TransactionHelper.java diff -u topia/src/java/org/codelutin/topia/persistence/TransactionHelper.java:1.1 topia/src/java/org/codelutin/topia/persistence/TransactionHelper.java:1.2 --- topia/src/java/org/codelutin/topia/persistence/TransactionHelper.java:1.1 Tue Jul 19 13:15:13 2005 +++ topia/src/java/org/codelutin/topia/persistence/TransactionHelper.java Wed Jul 20 12:49:52 2005 @@ -23,9 +23,9 @@ * Created: 16 juillet 2005 23:33:39 CEST * * @author Benjamin POUSSIN - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ * - * Last update: $Date: 2005/07/19 13:15:13 $ + * Last update: $Date: 2005/07/20 12:49:52 $ * by : $Author: bpoussin $ */ @@ -52,7 +52,7 @@ * Utilisé aussi pour les dates de modif des objets qui doivent * aussi etre unique pour le meme id */ - public long getDate(); + public long getUniqueDate(); } // TransactionHelper