Index: topia/src/java/org/codelutin/topia/persistence/PersistenceHelper.java diff -u topia/src/java/org/codelutin/topia/persistence/PersistenceHelper.java:1.14 topia/src/java/org/codelutin/topia/persistence/PersistenceHelper.java:1.15 --- topia/src/java/org/codelutin/topia/persistence/PersistenceHelper.java:1.14 Wed Sep 7 15:34:59 2005 +++ topia/src/java/org/codelutin/topia/persistence/PersistenceHelper.java Wed Sep 21 20:34:51 2005 @@ -23,21 +23,23 @@ * Created: Aug 1, 2004 * * @author Cédric Pineau - * @version $Revision: 1.14 $ + * @version $Revision: 1.15 $ * - * Last update : $Date: 2005/09/07 15:34:59 $ + * Last update : $Date: 2005/09/21 20:34:51 $ * by : $Author: bpoussin $ */ package org.codelutin.topia.persistence; +import java.io.Reader; +import java.io.Writer; 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.TopiaNotFoundException; import org.codelutin.topia.TopiaQuery; -import org.codelutin.topia.AsynchronousLoader; /** * @@ -113,13 +115,15 @@ * Charge le XML passé en paramètre dans la base * @param xml une chaine XML */ - public void importXML(String xml) throws TopiaException; + public void importXML(Reader xml) throws TopiaException; /** * Sauve toute la base en XML + * @param out le writer dans lequel il faut ecrire le flux XML + * @param entityClass la listes des classes des entites a exporter * @return une chaine XML */ - public String exportXML() throws TopiaException; + public void exportXML(Writer out, Class ... entityClass) throws TopiaException; /** * Recherche un objet par son identifiant @@ -127,7 +131,7 @@ public TopiaEntity findByTopiaId(String id) throws TopiaException; /** - * Renvoie si l'id correspond à une entité existante + * Renvoie vrai si l'id correspond à une entité existante */ public boolean exists(String id) throws TopiaException; Index: topia/src/java/org/codelutin/topia/persistence/PersistenceStorage.java diff -u topia/src/java/org/codelutin/topia/persistence/PersistenceStorage.java:1.7 topia/src/java/org/codelutin/topia/persistence/PersistenceStorage.java:1.8 --- topia/src/java/org/codelutin/topia/persistence/PersistenceStorage.java:1.7 Wed Aug 24 15:03:45 2005 +++ topia/src/java/org/codelutin/topia/persistence/PersistenceStorage.java Wed Sep 21 20:34:51 2005 @@ -23,9 +23,9 @@ * Created: 16 juillet 2005 23:40:21 CEST * * @author Benjamin POUSSIN - * @version $Revision: 1.7 $ + * @version $Revision: 1.8 $ * - * Last update: $Date: 2005/08/24 15:03:45 $ + * Last update: $Date: 2005/09/21 20:34:51 $ * by : $Author: bpoussin $ */ @@ -118,6 +118,12 @@ * Permet de savoir si un id existe encore dans le context de la transaction */ public boolean exists(TopiaContext context, String id) throws TopiaPersistenceException; + + /** + * Permet de recuperer toutes les classes d'objets gérées à l'instant de la + * demande par le storage, independament d'une transaction particuliere + */ + public List getPersistentClasses() throws TopiaPersistenceException; } // PersistenceStorage Index: topia/src/java/org/codelutin/topia/persistence/PersistenceStorageJDBC.java diff -u topia/src/java/org/codelutin/topia/persistence/PersistenceStorageJDBC.java:1.20 topia/src/java/org/codelutin/topia/persistence/PersistenceStorageJDBC.java:1.21 --- topia/src/java/org/codelutin/topia/persistence/PersistenceStorageJDBC.java:1.20 Wed Aug 24 15:03:45 2005 +++ topia/src/java/org/codelutin/topia/persistence/PersistenceStorageJDBC.java Wed Sep 21 20:34:51 2005 @@ -23,9 +23,9 @@ * Created: 20 juillet 2005 15:25:06 CEST * * @author Benjamin POUSSIN - * @version $Revision: 1.20 $ + * @version $Revision: 1.21 $ * - * Last update: $Date: 2005/08/24 15:03:45 $ + * Last update: $Date: 2005/09/21 20:34:51 $ * by : $Author: bpoussin $ */ @@ -45,11 +45,11 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; -import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; - +import java.util.Properties; import org.apache.commons.beanutils.MethodUtils; import org.apache.commons.dbcp.ConnectionFactory; import org.apache.commons.dbcp.DriverManagerConnectionFactory; @@ -635,7 +635,7 @@ ResultSet rr = sta.executeQuery(); while(rr.next()){ String field = rr.getString("field"); - if(data.getField(field) == data.UNLOADED){ + if(data.getField(field, context) == data.UNLOADED){ // on verife qu'il n'y ait pas deja // car cela voudrait dire que l'utilisateur a fait un set // avant le chargement des données @@ -644,7 +644,7 @@ String type = rr.getString("type"); byte[] bytesValue = rr.getBytes("value"); Object value = databaseToObject(context, type, bytesValue); - data.setField(field, value); + data.setField(field, value, context); // on vient de le charger, donc plus besoin de le faire tpo.getAskedFields().remove(field); } @@ -802,7 +802,6 @@ TopiaTransaction newtt = context.getTransaction().regenerateTransaction(); // peut-etre faire quelque chose comme dans beginTransaction ? // Comme on a fait un regenerateTransaction, le parent a deja pris en compte le changement de transaction, alors il faut impérativement le valider (au cas où une erreur survienne) - context.setTransaction(newtt); Connection conn = getConnection(); try{ PreparedStatement sta = conn.prepareStatement(SQL.getProperty(SQL_COMMIT_MANAGEMENT)); @@ -825,6 +824,7 @@ sta.close(); } conn.commit(); + context.setTransaction(newtt); } finally { if(!conn.isClosed()){ conn.close(); @@ -1000,6 +1000,15 @@ throw new TopiaPersistenceException("Erreur durant le test d'existance de l'entite: " + id, eee); } return result; + } + + /** + * Retourne la liste des classes qui ont déjà été demandé à être rendu + * persistante. Pour cela regarde dans la table de mapping + */ + public List getPersistentClasses() throws TopiaPersistenceException { + // FIXME + throw new UnsupportedOperationException("Pas encore implantée"); } } // PersistenceStorageJDBC Index: topia/src/java/org/codelutin/topia/persistence/PersistenceStorageJDBCMultiTable.java diff -u topia/src/java/org/codelutin/topia/persistence/PersistenceStorageJDBCMultiTable.java:1.4 topia/src/java/org/codelutin/topia/persistence/PersistenceStorageJDBCMultiTable.java:1.5 --- topia/src/java/org/codelutin/topia/persistence/PersistenceStorageJDBCMultiTable.java:1.4 Wed Sep 7 16:10:28 2005 +++ topia/src/java/org/codelutin/topia/persistence/PersistenceStorageJDBCMultiTable.java Wed Sep 21 20:34:51 2005 @@ -23,10 +23,10 @@ * Created: 20 juillet 2005 15:25:06 CEST * * @author Benjamin POUSSIN - * @version $Revision: 1.4 $ + * @version $Revision: 1.5 $ * - * Last update: $Date: 2005/09/07 16:10:28 $ - * by : $Author: thimel $ + * Last update: $Date: 2005/09/21 20:34:51 $ + * by : $Author: bpoussin $ */ package org.codelutin.topia.persistence; @@ -47,6 +47,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Date; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.List; @@ -56,6 +57,7 @@ import org.apache.commons.dbcp.DriverManagerConnectionFactory; import org.apache.commons.dbcp.PoolableConnectionFactory; import org.apache.commons.dbcp.PoolingDriver; +import org.apache.commons.lang.ClassUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -90,9 +92,20 @@ */ public class PersistenceStorageJDBCMultiTable implements PersistenceStorage { // PersistenceStorageJDBCMultiTable + final public static Class BYTES_CLASS = (new byte[0]).getClass(); + /** to use log facility, just put in your code: log.info(\"...\"); */ static private Log log = LogFactory.getLog(PersistenceStorageJDBCMultiTable.class); + static { + try{ + // on force l'init + log.debug("init de " + Class.forName("org.codelutin.topia.persistence.jdbctransformer.JDBCTransformerFactory")); + } catch (Exception eee){ + log.debug("Impossible d'initialiser JDBCTransformerFactory", eee); + } + } + protected Properties SQL = null; static private Properties SQL_DEFAULT = new Properties(); static private Properties SQL_POSTGRESQL = new Properties(SQL_DEFAULT); @@ -219,7 +232,7 @@ "DELETE FROM {0} WHERE topia_id=? and topia_longdate=?"); SQL_DEFAULT.put(SQL_GET_ALL_ID, "SELECT DISTINCT(topia_id) FROM {0} WHERE (topia_longdate in (" + Util.SQL_IDS_KEY + ") OR (topia_longdate>0 AND topia_longdate<=?)) AND topia_id NOT IN (SELECT topia_id FROM {0} WHERE topia_isDeleted=true AND (topia_longdate in (" + Util.SQL_IDS_KEY + ") OR (topia_longdate>0 AND topia_longdate<=?)))"); - +/* // Retourne la date de la derniere version valide de l'objet // {0} de nom de la table // SQL_IDS_KEY les ids de la transaction et des sous-transactions @@ -229,7 +242,7 @@ // ?3 l'id de la transaction en abs SQL_DEFAULT.put(SQL_GET_LONGDATE, "SELECT topia_longdate, topia_isDeleted from {0} where topia_id=? and topia_longdate=(SELECT min(topia_longdate) as topia_longdate from {0} where topia_id=? and abs(topia_longdate) = (SELECT max(abs(topia_longdate)) from {0} where topia_id=? and topia_longdate in (" + Util.SQL_IDS_KEY + ") or (topia_longdate>0 and topia_longdate <= ?)))"); - +*/ // {0} le nom de la table // {1} le nom des champs a inserer (commence par une ',') // {2} la valeur des champs a inserer (commence par une ',') @@ -531,6 +544,111 @@ } } + /** + * Permet de retourner la chaine reprensentant le type a utiliser pour + * la classe de l'attribut passé en parametre en fonction de la base + * courant + * @param clazz la classe de l'attribut, cette classe est deja la classe + * JDBC de l'objet, c-a-d que si l'attribut etait de type TopiaEntity + * la classe passée en argument devrait etre String + */ + protected String getSQLFieldType(Class clazz) { + String jdbcType = null; + + // pour les byte[] + if(BYTES_CLASS.equals(clazz)) { + jdbcType = SQL_TYPE_BYTES; + } else if(Object.class.equals(clazz)) { + jdbcType = SQL_TYPE_BYTES; + } else { + // pour les autres c une conversion automatique + // java.lang.Byte -> BYTE, ... + jdbcType = ClassUtils.getShortClassName(clazz).toUpperCase(); + } + String baseType = SQL.getProperty(jdbcType.toUpperCase()); + return baseType; + } + + /** + * Permet de mettre une valeur dans une statement pour une requete + * @param sta le statement dans lequel il faut mettre la valeur + * @param indice la position dans le statement + * @param clazz la classe JDBC de l'objet a mettre + * @param value la valeur de l'objet a mettre + */ + protected void putValue(PreparedStatement sta, int indice, Class clazz, + Object value) throws SQLException { + if (Boolean.class.equals(clazz)) { + sta.setBoolean(indice, ((Boolean)value).booleanValue()); + } else if (Byte.class.equals(clazz)) { + sta.setByte(indice, ((Byte)value).byteValue()); + } else if (BYTES_CLASS.equals(clazz)) { + sta.setBytes(indice, (byte[])value); + } else if (Date.class.equals(clazz)) { + if( !(value instanceof java.sql.Date)) { + value = new java.sql.Date(((java.util.Date)value).getTime()); + } + sta.setDate(indice, ((java.sql.Date)value)); + } else if (Double.class.equals(clazz)) { + sta.setDouble(indice, ((Double)value).doubleValue()); + } else if (Float.class.equals(clazz)) { + sta.setFloat(indice, ((Float)value).floatValue()); + } else if (Integer.class.equals(clazz)) { + sta.setInt(indice, ((Integer)value).intValue()); + } else if (Long.class.equals(clazz)) { + sta.setLong(indice, ((Long)value).longValue()); + } else if (Object.class.equals(clazz)) { + sta.setBytes(indice, (byte[])value); + } else if (Short.class.equals(clazz)) { + sta.setShort(indice, ((Short)value).shortValue()); + } else if (String.class.equals(clazz)) { + sta.setString(indice, (String)value); + } else { + throw new IllegalArgumentException("Can't put " + clazz + " in statement"); + } + } + + protected Object getValue(ResultSet rs, Class clazz, String columnName) throws SQLException { + Object result = null; + if (Boolean.class.equals(clazz)) { + boolean b = rs.getBoolean(columnName); + result = b?Boolean.TRUE:Boolean.FALSE; + } else if (Byte.class.equals(clazz)) { + byte b = rs.getByte(columnName); + return Byte.valueOf(b); + } else if (BYTES_CLASS.equals(clazz)) { + result = rs.getBytes(columnName); + } else if (Date.class.equals(clazz)) { + result = rs.getDate(columnName); + } else if (Double.class.equals(clazz)) { + double b = rs.getDouble(columnName); + return Double.valueOf(b); + } else if (Float.class.equals(clazz)) { + float b = rs.getFloat(columnName); + return Float.valueOf(b); + } else if (Integer.class.equals(clazz)) { + int b = rs.getInt(columnName); + return Integer.valueOf(b); + } else if (Long.class.equals(clazz)) { + long b = rs.getLong(columnName); + return Long.valueOf(b); + } else if (Object.class.equals(clazz)) { + result = rs.getBytes(columnName); + } else if (Short.class.equals(clazz)) { + short b = rs.getShort(columnName); + return Short.valueOf(b); + } else if (String.class.equals(clazz)) { + result = rs.getString(columnName); + } else { + throw new IllegalArgumentException("Can't put " + clazz + " in statement"); + } + return result; + } + + /** + * @param clazz la class de l'objet que l'on veut stocker + * @return la chaine SQL de declaration des champs de la class + */ protected String getSQLFieldDeclaration(Class clazz) { try{ CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".getSQLFieldDeclaration"); @@ -538,8 +656,8 @@ String [] fieldnames = ClassInfoHelper.fields(clazz); Class [] fieldTypes = ClassInfoHelper.fieldTypes(clazz); for(int i=0; i 0){ + if(tmp > 0 || context.getTransaction().containsId(tmp)){ if(!rr.getBoolean("topia_isDeleted")) { result = tmp; } @@ -1168,8 +1284,8 @@ query = Util.setAllMultipleIds(query, context.getTransaction()); PreparedStatement sta = conn.prepareStatement(query); try{ - sta.setLong(1, -context.getTransaction().getId()); - sta.setLong(2, -context.getTransaction().getId()); + sta.setLong(1, context.getTransaction().getLastView()); + sta.setLong(2, context.getTransaction().getLastView()); ResultSet rr = sta.executeQuery(); while(rr.next()){ result.add(rr.getString("topia_id")); @@ -1217,10 +1333,9 @@ CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".commitTransaction"); try{ TopiaTransaction actualtt = context.getTransaction(); - TopiaTransaction newtt = context.getTransaction().regenerateTransaction(); + TopiaTransaction newtt = actualtt.regenerateTransaction(); // peut-etre faire quelque chose comme dans beginTransaction ? // Comme on a fait un regenerateTransaction, le parent a deja pris en compte le changement de transaction, alors il faut impérativement le valider (au cas où une erreur survienne) - context.setTransaction(newtt); Connection conn = getConnection(); try{ String allTableSql = MessageFormat.format(SQL.getProperty(SQL_LOAD_ALL), "topia_mapping_table"); @@ -1241,6 +1356,7 @@ } } conn.commit(); + context.setTransaction(newtt); } finally { if(!conn.isClosed()){ conn.close(); @@ -1449,6 +1565,38 @@ return result; } finally { CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".exists"); + } + } + + public List getPersistentClasses() throws TopiaPersistenceException { + try{ + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".getPersistentClasses"); + List result = new ArrayList(); + try { + Connection conn = getConnection(); + try { + String sql = MessageFormat.format(SQL.getProperty(SQL_LOAD_ALL), "topia_mapping_table"); + PreparedStatement stat = conn.prepareStatement(sql); + ResultSet rs = stat.executeQuery(); + while (rs.next()){ + String classname = rs.getString("topia_class"); + try { + Class clazz = Util.getClazz(classname); + result.add(clazz); + } catch (TopiaNotFoundException eee){ + throw new TopiaPersistenceException("Impossible de charger la classe: " + classname, eee); + } + } + conn.commit(); + } finally { + conn.close(); + } + return result; + } catch(SQLException eee){ + throw new TopiaPersistenceException("Erreur durant la recherche des classes géré par le storage", eee); + } + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".getPersistentClasses"); } } Index: topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceCache.java diff -u topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceCache.java:1.5 topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceCache.java:1.6 --- topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceCache.java:1.5 Thu Aug 11 16:42:27 2005 +++ topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceCache.java Wed Sep 21 20:34:51 2005 @@ -23,10 +23,10 @@ * Created: 16 juillet 2005 23:42:14 CEST * * @author Benjamin POUSSIN - * @version $Revision: 1.5 $ + * @version $Revision: 1.6 $ * - * Last update: $Date: 2005/08/11 16:42:27 $ - * by : $Author: thimel $ + * Last update: $Date: 2005/09/21 20:34:51 $ + * by : $Author: bpoussin $ */ package org.codelutin.topia.persistence; @@ -80,13 +80,15 @@ (TopiaPersistenceProxy)Proxy.getInvocationHandler(entity); TopiaPersistenceObject tpo = tpp.getObject(); tpo.getManagement().setRollbacked(true); - tpo.getData().clear(); + for(String attName: tpo.getData().keySet()){ + tpo.getData().get(attName).setJavaValue(tpo.getData().UNLOADED); + } } } } public void putAll(TopiaPersistenceCache cache){ - cache.putAll(cache); + this.cache.putAll(cache.cache); } } // TopiaPersistenceCache Index: topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceHelper.java diff -u topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceHelper.java:1.11 topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceHelper.java:1.12 --- topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceHelper.java:1.11 Wed Sep 7 15:34:59 2005 +++ topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceHelper.java Wed Sep 21 20:34:51 2005 @@ -23,15 +23,17 @@ * Created: Jul 16, 2005 * * @author Benjamin POUSSIN - * @version $Revision: 1.11 $ + * @version $Revision: 1.12 $ * - * Last update : $Date: 2005/09/07 15:34:59 $ + * Last update : $Date: 2005/09/21 20:34:51 $ * by : $Author: bpoussin $ */ package org.codelutin.topia.persistence; import java.io.IOException; +import java.io.Reader; +import java.io.Writer; import java.lang.IllegalStateException; import java.lang.reflect.Proxy; import java.util.ArrayList; @@ -40,6 +42,7 @@ import java.util.Properties; import org.codelutin.querycollection.CollectionQueryHelper; import org.codelutin.queryparser.QueryHelperException; +import org.codelutin.topia.annotation.ClassInfoHelper; import org.codelutin.topia.AsynchronousLoader; import org.codelutin.topia.TopiaConst; import org.codelutin.topia.TopiaContext; @@ -48,7 +51,7 @@ import org.codelutin.topia.TopiaId; import org.codelutin.topia.TopiaNotFoundException; import org.codelutin.topia.TopiaQuery; -import org.codelutin.topia.annotation.ClassInfoHelper; +import org.codelutin.topia.Util; public class TopiaPersistenceHelper implements PersistenceHelper { // TopiaPersistenceHelper @@ -178,6 +181,11 @@ } // l'objet venait d'un autre PersistenceHelper, il faut en recreer // un pour nous + + // FIXME verifier que le clone fonctionne bien, qu'il ne reste + // pas d'objet de l'ancien context dans cet objet + // peut-etre faire une sauvegarde dans ce context + restauration + // pour etre sur d'avoir que des objets a nous tpo = tpo.clone(); tpo.getManagement().setNew(true); tpo.getManagement().setStored(false); @@ -260,8 +268,10 @@ } } else { List entities = new ArrayList(); + + Class fromClass = Util.getClazz(query.getFrom()); for(String id: getStorage().getAllId(getContext())){ - if(TopiaId.getClassNameAsString(id).equals(query.getFrom())){ + if(TopiaId.getClassName(id).isAssignableFrom(fromClass)){ entities.add(findByTopiaId(id)); } } @@ -296,14 +306,15 @@ } - public void importXML(String xml) throws TopiaException { + public void importXML(Reader xml) throws TopiaException { // TODO throw new UnsupportedOperationException(); } - public String exportXML() throws TopiaException { - // TODO - throw new UnsupportedOperationException(); + public void exportXML(Writer out, Class ... entityClass) throws TopiaException { + // TODO recuperation des instance de class entityClass + // conversion en XML. La recherche des entityClass doit être + // strict, c-a-d que l'on ne prend pas les objet parents } public boolean exists(String id) throws TopiaException { Index: topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceObject.java diff -u topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceObject.java:1.4 topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceObject.java:1.5 --- topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceObject.java:1.4 Wed Aug 24 15:03:45 2005 +++ topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceObject.java Wed Sep 21 20:34:51 2005 @@ -23,9 +23,9 @@ * Created: 16 juillet 2005 23:44:18 CEST * * @author Benjamin POUSSIN - * @version $Revision: 1.4 $ + * @version $Revision: 1.5 $ * - * Last update: $Date: 2005/08/24 15:03:45 $ + * Last update: $Date: 2005/09/21 20:34:51 $ * by : $Author: bpoussin $ */ @@ -38,6 +38,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.codelutin.topia.annotation.ClassInfoHelper; +import org.codelutin.topia.TopiaContext; import org.codelutin.topia.Util; public class TopiaPersistenceObject implements Serializable, Cloneable { // TopiaPersistenceObject @@ -53,6 +54,19 @@ public TopiaPersistenceObject(String id){ management = new TopiaPersistenceObjectManagementData(id); data = new TopiaPersistenceObjectData(); + + Class clazz = getManagement().getEntityClass(); + TopiaPersistenceObjectData data = getData(); + + // On met en place les Lazy pour qu'il ne soit pas toujours recree + // par la suite + String [] fields = ClassInfoHelper.fields(clazz); + Class [] fieldTypes = ClassInfoHelper.fieldTypes(clazz); + for(int i=0; i - * @version $Revision: 1.2 $ + * @version $Revision: 1.3 $ * - * Last update: $Date: 2005/07/20 12:49:52 $ + * Last update: $Date: 2005/09/21 20:34:51 $ * by : $Author: bpoussin $ */ @@ -34,8 +34,9 @@ import java.util.HashMap; import java.util.logging.Level; import java.util.logging.Logger; +import org.codelutin.topia.TopiaContext; -public class TopiaPersistenceObjectData extends HashMap { // TopiaPersistenceObjectData +public class TopiaPersistenceObjectData extends HashMap { // TopiaPersistenceObjectData /** to use log facility, just put in your code: log.info(\"...\"); */ static private Logger log = Logger.getLogger("org.codelutin.topia.persistence.TopiaPersistenceObjectData"); @@ -44,19 +45,20 @@ public TopiaPersistenceObjectData(){} - public Object getField(String fieldName){ - Object result = UNLOADED; - if(containsKey(fieldName)){ - result = super.get(fieldName); - } + public Object getField(String fieldName, TopiaContext context){ + LazyAttibute att = get(fieldName); + Object result = att.getJavaValue(context); return result; } - public Object setField(String fieldName, Object value){ + public Object setField(String fieldName, Object value, TopiaContext context){ if(value == UNLOADED){ throw new IllegalArgumentException("La variable UNLOADED ne peut pas être affectée à un champs"); } - return put(fieldName, value); + LazyAttibute att = get(fieldName); + Object old = att.getJavaValue(context); + att.setJavaValue(value); + return old; } } // TopiaPersistenceObjectData Index: topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceProxy.java diff -u topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceProxy.java:1.15 topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceProxy.java:1.16 --- topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceProxy.java:1.15 Fri Sep 16 15:52:14 2005 +++ topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceProxy.java Wed Sep 21 20:34:51 2005 @@ -23,10 +23,10 @@ * Created: 16 juillet 2005 23:52:35 CEST * * @author Benjamin POUSSIN -* @version $Revision: 1.15 $ +* @version $Revision: 1.16 $ * -* Last update: $Date: 2005/09/16 15:52:14 $ -* by : $Author: thimel $ +* Last update: $Date: 2005/09/21 20:34:51 $ +* by : $Author: bpoussin $ */ package org.codelutin.topia.persistence; @@ -129,7 +129,7 @@ } protected void setField(String fieldName, Object value){ - getObject().setField(fieldName, value); + getObject().setField(fieldName, value, ph.getContext()); // on vient de modifier au moins un champs // donc l'objet doit rentrer dans la transaction getObject().getManagement().setDate(ph.getContext().getTransaction().getId()); @@ -137,12 +137,12 @@ protected Object getField(TopiaEntity entity, String fieldName, Class fieldType) throws Exception { // methode pour acceder au champs - Object result = getObject().getField(fieldName); + Object result = getObject().getField(fieldName, ph.getContext()); if(result == getObject().getData().UNLOADED){ if(!getObject().getManagement().isNew()){ // si l'objet existait avant, on essai de charger la valeur ph.load(entity); - result = o.getField(fieldName); + result = o.getField(fieldName, ph.getContext()); } if(result == getObject().getData().UNLOADED){ // toujours pas de valeur, soit parce que l'objet est nouveau @@ -492,10 +492,17 @@ // on pointe vers une class sans qu'il y ait de classe // d'association pour conserver la relation, on // fait donc juste une conversion en id + // + // FIXME 20050921 bpoussin: non plus maintenant avec les + // JDBCTransformer et le LazyAttibute. donc + // quand ca marche refactore le code pour peut-etre + // faire la meme chose qu'un champs normal if(MethodInfoHelper.isFieldModifier(method)){ // methode pour modifier le champs TopiaEntity value = (TopiaEntity)args[0]; - setField(fieldName, value.get_topiaId_()); + // FIXME code a supprime voir FIXME plus haut + // setField(fieldName, value.get_topiaId_()); + setField(fieldName, value); if(ph.isAutoUpdate()){ getPersistenceService().update((TopiaEntity)proxy); } @@ -509,9 +516,11 @@ result + "\" n'existe pas. Le champ \"" + fieldName + "\" est mis à null."); result = null; - } else { - result = ph.findByTopiaId((String)result); } + // FIXME code a supprime voir FIXME plus haut + // else { + // result = ph.findByTopiaId((String)result); + // } return result; } } else { Index: topia/src/java/org/codelutin/topia/persistence/TopiaTransaction.java diff -u topia/src/java/org/codelutin/topia/persistence/TopiaTransaction.java:1.5 topia/src/java/org/codelutin/topia/persistence/TopiaTransaction.java:1.6 --- topia/src/java/org/codelutin/topia/persistence/TopiaTransaction.java:1.5 Thu Aug 11 16:42:27 2005 +++ topia/src/java/org/codelutin/topia/persistence/TopiaTransaction.java Wed Sep 21 20:34:51 2005 @@ -23,10 +23,10 @@ * Created: 16 juillet 2005 22:54:16 CEST * * @author Benjamin POUSSIN - * @version $Revision: 1.5 $ + * @version $Revision: 1.6 $ * - * Last update: $Date: 2005/08/11 16:42:27 $ - * by : $Author: thimel $ + * Last update: $Date: 2005/09/21 20:34:51 $ + * by : $Author: bpoussin $ */ package org.codelutin.topia.persistence; @@ -78,6 +78,48 @@ } /** + * Une sous-transaction doit avoir la vision de ces objets, mais aussi + * des objets de ses ancetres. Cette methode retourne en valeur absolue + * la plus grande date entre la transaction courante et ses parent. + * Cette methode est necessaire, car meme si au depart les sous transactions + * sont toujours superieur en valeur absolue a leur pere, apres des commits + * cela n'est plus vrai. + *

+ * Il serait plus couteux de modifier tous les transactions de tous les + * context fils. On ne peut pas juste modifier les id dans les transactions + * car les transactions ne doivent pas change d'id, les hashtables ayant + * les transactions en cle, ne le supporterait pas. + * De plus cela voudrait dire beaucoup de generation d'id en plus, et dans + * un context reseau cette generation est faite cote serveur ce qui serait + * tres penalisant. + */ + public long getLastView() { + long result = 0; + TopiaTransaction tt = this; + while(tt != null){ + if (-tt.getId() > result) { + result = -tt.getId(); + } + tt = tt.getParent(); + } + return result; + } + + /** + * Verifie que l'id passé en parametre est un id valid pour cette transaction + * c-a-d qu'il est egal a l'id de la transaction courante ou une + * transaction pere + */ + public boolean containsId(long id){ + TopiaTransaction tt = this; + while(id != tt.getId() && tt.getParent() != null){ + tt = tt.getParent(); + } + boolean result = (id == tt.getId()); + return result; + } + + /** * Retourne tous l'id de la transaction et de ces parents */ public long [] getIds(){ @@ -125,11 +167,44 @@ } public TopiaTransaction newSubTransaction(){ - TopiaTransaction result = new TopiaTransaction(this); - childs.add(result); - return result; + TopiaTransaction result = new TopiaTransaction(this); + childs.add(result); + return result; + } + + /** + * Prepare une nouvelle transaction pour etre utiliser apres le commit + * Si le commit se passe bien, il faut ensuite appeler swapTransaction + * avec la nouvelle transaction en parametre + */ + public TopiaTransaction regenerateTransaction(){ + TopiaTransaction result = tth.newTranstaction(); + if (getParent() != null) { + result.setParent(getParent()); + } + return result; + } + + /** + * Si le commit se passe bien, il faut appeler cette methode avec la + * nouvelle transaction en parametre. la transaction courante ne + * doit plus etre utilisé. Cette methode est appelé dans setTransaction + * du context + */ + public void swapTransaction(TopiaTransaction newtt){ + if (getParent() != null) { + getParent().getChilds().remove(this); + getParent().getChilds().add(newtt); + } + // si on a des enfants, il faut aussi les garder :) + newtt.getChilds().addAll(getChilds()); + // pour dire aux enfants qu'ils changent de père + for (TopiaTransaction tt : newtt.getChilds()) { + tt.setParent(newtt); + } } + /* public TopiaTransaction regenerateTransaction(){ TopiaTransaction result = null; if(getParent() == null){ @@ -146,6 +221,7 @@ } return result; } +*/ public int compareTo(TopiaTransaction o){ if(getId() < o.getId()){ Index: topia/src/java/org/codelutin/topia/persistence/LazyAttibute.java diff -u /dev/null topia/src/java/org/codelutin/topia/persistence/LazyAttibute.java:1.1 --- /dev/null Wed Sep 21 20:34:56 2005 +++ topia/src/java/org/codelutin/topia/persistence/LazyAttibute.java Wed Sep 21 20:34:51 2005 @@ -0,0 +1,90 @@ +/* *##% + * Copyright (C) 2005 + * 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. + *##%*/ + +/* * + * LazyAttibute.java + * + * Created: 14 septembre 2005 03:07:17 CEST + * + * @author Benjamin POUSSIN + * @version $Revision: 1.1 $ + * + * Last update: $Date: 2005/09/21 20:34:51 $ + * by : $Author: bpoussin $ + */ + +package org.codelutin.topia.persistence; + +import java.util.HashMap; +import java.util.Map; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codelutin.topia.persistence.jdbctransformer.JDBCTransformer; +import org.codelutin.topia.TopiaContext; +import org.codelutin.util.FormatConverter; +import org.codelutin.util.FormatConverterFactory; +import org.codelutin.util.FormatMap; +import org.codelutin.xml.XMLConverter; +import org.dom4j.Element; +/** +* Cette classe permet de ne faire la conversion de JDBC vers Java ou +* de XML vers JDBC, etc que lorsqu'il y a vraiment besoin +*/ +public class LazyAttibute extends FormatMap { // LazyAttibute + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(LazyAttibute.class); + + /** utilisé pour le UNLOADED object */ + LazyAttibute(){ + super(null); + } + + public LazyAttibute(Class clazz){ + super(clazz); + } + + public Object getJDBCValue(TopiaContext context) { + return convert(JDBCTransformer.FORMAT_JDBC, context); + } + + public void setJDBCValue(Object value) { + setValue(JDBCTransformer.FORMAT_JDBC, value); + } + + public Object getJavaValue(TopiaContext context) { + return convert(FormatConverter.FORMAT_JAVA, context); + } + + public void setJavaValue(Object value) { + setValue(FormatConverter.FORMAT_JAVA, value); + } + + // TODO cette methode devrait retourne String + public Element getXMLValue(TopiaContext context) { + return (Element)convert(XMLConverter.FORMAT_XML, context); + } + + // TODO cette methode devrait prendre String en arg + public void setXMLValue(Element value) { + setValue(XMLConverter.FORMAT_XML, value); + } + +} // LazyAttibute +