r2807 - in trunk/topia-persistence/src/main/java/org/nuiton/topia: . framework generator persistence
Author: bleny Date: 2013-10-01 15:15:11 +0200 (Tue, 01 Oct 2013) New Revision: 2807 Url: http://nuiton.org/projects/topia/repository/revisions/2807 Log: refs #2087 introduce AbstractTopiaDAO and a new query builder, use it to replace TopiaDAOImpl Added: trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaDAOSupplier.java trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/AbstractTopiaDAO.java trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/HqlAndParametersBuilder.java Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/AbstractTopiaPersistenceContext.java trunk/topia-persistence/src/main/java/org/nuiton/topia/HibernateTopiaJpaSupport.java trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaJpaSupport.java trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaPersistenceContext.java trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/AbstractTopiaContext.java trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaContextImplementor.java trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaFiresSupport.java trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaUtil.java trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityDAOTransformer.java trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/PersistenceContextTransformer.java trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/TopiaGeneratorUtil.java trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaDAO.java trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaDAOImpl.java trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaEntityAbstract.java trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaEntityContextable.java Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/AbstractTopiaPersistenceContext.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/AbstractTopiaPersistenceContext.java 2013-09-27 18:43:30 UTC (rev 2806) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/AbstractTopiaPersistenceContext.java 2013-10-01 13:15:11 UTC (rev 2807) @@ -24,10 +24,9 @@ * #L% */ -import java.util.List; -import java.util.Map; -import java.util.Properties; - +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.HibernateException; @@ -37,14 +36,15 @@ import org.hibernate.tool.hbm2ddl.SchemaUpdate; import org.nuiton.topia.framework.TopiaFiresSupport; import org.nuiton.topia.framework.TopiaUtil; +import org.nuiton.topia.persistence.AbstractTopiaDAO; import org.nuiton.topia.persistence.TopiaDAO; -import org.nuiton.topia.persistence.TopiaDAOImpl; import org.nuiton.topia.persistence.TopiaEntity; import org.nuiton.topia.persistence.TopiaIdFactory; -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; +import java.lang.reflect.InvocationTargetException; +import java.util.List; +import java.util.Map; +import java.util.Properties; /** * Abstract implementation of the TopiaPersistenceContext. This class will be extended by a generated one in order to @@ -177,27 +177,42 @@ entityClass.getName())); } - TopiaDAOImpl<E> result = (TopiaDAOImpl<E>) daoCache.get(entityClass); - if (result == null) { + TopiaDAO<E> dao = (TopiaDAO<E>) daoCache.get(entityClass); + if (dao == null) { // Looking for specialized DAO // This DAO is supposed to exist, as created by generation String daoClassName = entityClass.getName() + "DAO"; try { - Class<TopiaDAOImpl<E>> daoClass = (Class<TopiaDAOImpl<E>>) Class.forName(daoClassName); - result = daoClass.getConstructor().newInstance(); - } catch (Exception eee) { - log.fatal("specialized DAO " + daoClassName + - " not found, use default TopiaDAOHibernate"); - throw new TopiaException("Specialized DAO " + daoClassName + " not found"); + Class<TopiaDAO<E>> daoClass = (Class<TopiaDAO<E>>) Class.forName(daoClassName); + dao = daoClass.getConstructor().newInstance(); + } catch (InstantiationException e) { + log.fatal("unable to instantiate DAO class " + daoClassName, e); + throw new TopiaException("unable to instantiate DAO class " + daoClassName, e); + } catch (IllegalAccessException e) { + log.fatal("unable to instantiate DAO class " + daoClassName, e); + throw new TopiaException("unable to instantiate DAO class " + daoClassName, e); + } catch (InvocationTargetException e) { + log.fatal("unable to instantiate DAO class " + daoClassName, e); + throw new TopiaException("unable to instantiate DAO class " + daoClassName, e); + } catch (NoSuchMethodException e) { + log.fatal("unable to instantiate DAO class " + daoClassName, e); + throw new TopiaException("unable to instantiate DAO class " + daoClassName, e); + } catch (ClassNotFoundException e) { + log.fatal("unable to find DAO class " + daoClassName, e); + throw new TopiaException("unable to find DAO class " + daoClassName, e); } - // AThimel 27/09/13 "entityClass" seems not to be needed anymore in DAO init(...) method - // TODO AThimel 27/09/13 Uncomment the next line -// result.init(hibernateSupport, jpaSupport, sqlSupport, listenableSupport, topiaIdFactory, firesSupport); - daoCache.put(entityClass, result); + if (dao instanceof AbstractTopiaDAO) { + AbstractTopiaDAO abstractTopiaDAO = (AbstractTopiaDAO) dao; + abstractTopiaDAO.init(hibernateSupport, jpaSupport, sqlSupport, listenableSupport, topiaIdFactory, firesSupport, this); + } + + daoCache.put(entityClass, dao); + } - return result; + + return dao; } @Override Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/HibernateTopiaJpaSupport.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/HibernateTopiaJpaSupport.java 2013-09-27 18:43:30 UTC (rev 2806) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/HibernateTopiaJpaSupport.java 2013-10-01 13:15:11 UTC (rev 2807) @@ -24,16 +24,15 @@ * #L% */ -import java.util.Collection; -import java.util.List; -import java.util.Map; - import org.hibernate.FlushMode; import org.hibernate.HibernateException; import org.hibernate.Query; import org.nuiton.topia.framework.TopiaFiresSupport; +import org.nuiton.topia.framework.TopiaUtil; -import com.google.common.collect.Maps; +import java.util.Collection; +import java.util.List; +import java.util.Map; /** * This class is the Hibernate implementation of TopiaJpaSupport. It realizes the bridge between the JPA specification @@ -140,28 +139,6 @@ } @Override - public <T> T findUnique(String jpaql, Map<String, Object> parameters) { - checkClosed(); - - List<T> results = find(jpaql, 0, 1, parameters); - - // If there is more than 1 result, throw an exception - if (results.size() > 1) { - String message = String.format( - "The query '%s' returns more than 1 unique result", jpaql); - // TODO AThimel 02/08/13 Throw another exception if more than 1 result is found - throw new TopiaException(message); - } - - // otherwise return the first one, or null - T result = null; - if (!results.isEmpty()) { - result = results.get(0); - } - return result; - } - - @Override public int execute(String jpaql, Map<String, Object> parameters) { checkClosed(); @@ -180,42 +157,30 @@ } } - protected Map<String, Object> asMap(Object[] propertyNamesAndValues) { - Map<String, Object> result = Maps.newHashMap(); - if (propertyNamesAndValues != null) { - for (int j = 0; j < propertyNamesAndValues.length; j += 2) { - String name = (String) propertyNamesAndValues[j]; - Object value = propertyNamesAndValues[j + 1]; - result.put(name, value); - } - } - return result; - } - @Override public <T> List<T> findAll(String jpaql, Object... propertyNamesAndValues) { - Map<String, Object> parameters = asMap(propertyNamesAndValues); + Map<String, Object> parameters = TopiaUtil.convertPropertiesArrayToMap(propertyNamesAndValues); List<T> result = findAll(jpaql, parameters); return result; } @Override public <T> List<T> find(String jpaql, int startIndex, int endIndex, Object... propertyNamesAndValues) { - Map<String, Object> parameters = asMap(propertyNamesAndValues); + Map<String, Object> parameters = TopiaUtil.convertPropertiesArrayToMap(propertyNamesAndValues); List<T> result = find(jpaql, startIndex, endIndex, parameters); return result; } @Override public <T> T findUnique(String jpaql, Object... propertyNamesAndValues) { - Map<String, Object> parameters = asMap(propertyNamesAndValues); + Map<String, Object> parameters = TopiaUtil.convertPropertiesArrayToMap(propertyNamesAndValues); T result = findUnique(jpaql, parameters); return result; } @Override public int execute(String jpaql, Object... propertyNamesAndValues) { - Map<String, Object> parameters = asMap(propertyNamesAndValues); + Map<String, Object> parameters = TopiaUtil.convertPropertiesArrayToMap(propertyNamesAndValues); int result = execute(jpaql, parameters); return result; } Added: trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaDAOSupplier.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaDAOSupplier.java (rev 0) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaDAOSupplier.java 2013-10-01 13:15:11 UTC (rev 2807) @@ -0,0 +1,30 @@ +package org.nuiton.topia; + +import org.nuiton.topia.persistence.TopiaDAO; +import org.nuiton.topia.persistence.TopiaEntity; + +/** + * @author bleny + */ +public interface TopiaDAOSupplier { + + /** + * Get DAO for specified class. If Specialized DAO exists then it returned + * otherwize TopiaDAO<entityClass> is returned + * + * @param entityClass type of entity + * @return the expected dao + */ + <E extends TopiaEntity> TopiaDAO<E> getDAO(Class<E> entityClass); + + /** + * Get DAO for specified class. If Specialized DAO exists then it returned + * otherwize TopiaDAO<entityClass> is returned + * + * @param entityClass type of entity + * @param daoClass the concrete dao class to use + * @return the expected dao + */ + <E extends TopiaEntity, D extends TopiaDAO<E>> D getDAO(Class<E> entityClass, Class<D> daoClass); + +} Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaJpaSupport.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaJpaSupport.java 2013-09-27 18:43:30 UTC (rev 2806) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaJpaSupport.java 2013-10-01 13:15:11 UTC (rev 2807) @@ -117,25 +117,10 @@ * support something else than queries on TopiaEntity * * @param jpaql the JPA-QL query - * @param parameters a map which keys are the attribute names and values are the attributes expected values - * @return The result instance or null - */ - <T> T findUnique(String jpaql, - Map<String, Object> parameters); - - /** - * Allow to do some JPA-QL query and return an unique result. If nothing if - * found by the query, will return null. If more than one result is found, - * will throw an exception. - * <p/> - * WARNING : Depending on the registered service, this method may not - * support something else than queries on TopiaEntity - * - * @param jpaql the JPA-QL query * @param propertyNamesAndValues the query parameters. Arguments are key-value paired : * [propertyName;value;propertyName;value;...] * @return The result instance or null - * @deprecated prefer using {@link #findUnique(String, java.util.Map)} + * @deprecated prefer using {@link #find(String, int, int, java.util.Map)} */ @Deprecated <T> T findUnique(String jpaql, Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaPersistenceContext.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaPersistenceContext.java 2013-09-27 18:43:30 UTC (rev 2806) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaPersistenceContext.java 2013-10-01 13:15:11 UTC (rev 2807) @@ -24,13 +24,12 @@ * #L% */ -import java.util.List; -import java.util.Properties; - -import org.nuiton.topia.persistence.TopiaDAO; import org.nuiton.topia.persistence.TopiaEntity; import org.nuiton.topia.persistence.TopiaIdFactory; +import java.util.List; +import java.util.Properties; + /** * This API provides all methods related to persistence : * <ul> @@ -42,7 +41,7 @@ * @author Arnaud Thimel <thimel@codelutin.com> * @since 3.0 */ -public interface TopiaPersistenceContext { +public interface TopiaPersistenceContext extends TopiaDAOSupplier { /** * Retrieve {@link org.nuiton.topia.persistence.TopiaEntity} using its unique {@code topiaId}. @@ -79,25 +78,6 @@ Properties getConfig(); // TODO AThimel 02/08/13 Change type ? /** - * Get DAO for specified class. If Specialized DAO exists then it returned - * otherwize TopiaDAO<entityClass> is returned - * - * @param entityClass type of entity - * @return the expected dao - */ - <E extends TopiaEntity> TopiaDAO<E> getDAO(Class<E> entityClass); - - /** - * Get DAO for specified class. If Specialized DAO exists then it returned - * otherwize TopiaDAO<entityClass> is returned - * - * @param entityClass type of entity - * @param daoClass the concrete dao class to use - * @return the expected dao - */ - <E extends TopiaEntity, D extends TopiaDAO<E>> D getDAO(Class<E> entityClass, Class<D> daoClass); - - /** * Detects if the db associated to the current context contains at least one * entity table. * Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/AbstractTopiaContext.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/AbstractTopiaContext.java 2013-09-27 18:43:30 UTC (rev 2806) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/AbstractTopiaContext.java 2013-10-01 13:15:11 UTC (rev 2807) @@ -25,29 +25,6 @@ package org.nuiton.topia.framework; -import java.beans.PropertyChangeListener; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; -import java.lang.reflect.Field; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.WeakHashMap; -import java.util.zip.GZIPInputStream; - import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -81,12 +58,36 @@ import org.nuiton.topia.event.TopiaSchemaListener; import org.nuiton.topia.event.TopiaTransactionListener; import org.nuiton.topia.event.TopiaTransactionVetoable; +import org.nuiton.topia.persistence.AbstractTopiaDAO; import org.nuiton.topia.persistence.DefaultTopiaIdFactory; import org.nuiton.topia.persistence.TopiaDAO; import org.nuiton.topia.persistence.TopiaDAOImpl; import org.nuiton.topia.persistence.TopiaEntity; import org.nuiton.topia.persistence.TopiaIdFactory; +import java.beans.PropertyChangeListener; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.WeakHashMap; +import java.util.zip.GZIPInputStream; + /** * Le AbstractTopiaContext est le point d'entre pour acceder aux donnees. Il est * configurer par un fichier de propriete @@ -1099,11 +1100,6 @@ } @Override - public <T> T findUnique(String jpaql, Map<String, Object> parameters) { - throw new UnsupportedOperationException("This method is not available on TopiaContext, please use TopiaJpaSupport"); - } - - @Override public int execute(String jpaql, Map<String, Object> parameters) { throw new UnsupportedOperationException("This method is not available on TopiaContext, please use TopiaJpaSupport"); } Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaContextImplementor.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaContextImplementor.java 2013-09-27 18:43:30 UTC (rev 2806) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaContextImplementor.java 2013-10-01 13:15:11 UTC (rev 2807) @@ -161,7 +161,7 @@ * @deprecated use method from {@link org.nuiton.topia.TopiaPersistenceContext} */ @Deprecated - <E extends TopiaEntity, D extends TopiaDAO<E>> D getDAO(Class<E> entityClass,Class<D> daoClass) + <E extends TopiaEntity, D extends TopiaDAO<E>> D getDAO(Class<E> entityClass, Class<D> daoClass) throws TopiaException; /** Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaFiresSupport.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaFiresSupport.java 2013-09-27 18:43:30 UTC (rev 2806) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaFiresSupport.java 2013-10-01 13:15:11 UTC (rev 2807) @@ -25,16 +25,6 @@ package org.nuiton.topia.framework; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.beans.VetoableChangeSupport; -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.lang3.StringUtils; import org.apache.commons.logging.Log; @@ -49,8 +39,6 @@ import org.hibernate.event.spi.PostLoadEventListener; import org.hibernate.event.spi.PostUpdateEvent; import org.hibernate.event.spi.PostUpdateEventListener; -import org.hibernate.event.spi.PreCollectionUpdateEvent; -import org.hibernate.event.spi.PreCollectionUpdateEventListener; import org.hibernate.event.spi.PreDeleteEvent; import org.hibernate.event.spi.PreDeleteEventListener; import org.hibernate.event.spi.PreInsertEvent; @@ -77,11 +65,22 @@ import org.nuiton.topia.event.TopiaTransactionEvent; import org.nuiton.topia.event.TopiaTransactionListener; import org.nuiton.topia.event.TopiaTransactionVetoable; +import org.nuiton.topia.persistence.AbstractTopiaDAO; import org.nuiton.topia.persistence.TopiaEntity; import org.nuiton.topia.persistence.TopiaEntityContextable; import org.nuiton.util.CategorisedListenerSet; import org.nuiton.util.ListenerSet; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.beans.VetoableChangeSupport; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + /** * TODO-fdesbois-20100507 : Need translation of javadoc. * <p/> @@ -323,7 +322,7 @@ } } - public void fireOnPostLoad(TopiaContextImplementor context, + public void fireOnPostLoad(AbstractTopiaDAO context, TopiaEntity entity, Object[] state) { if (log.isDebugEnabled()) { log.debug("fireOnPostLoad"); @@ -606,16 +605,16 @@ } private void attachContext(Object entity, - TopiaContextImplementor context) { + AbstractTopiaDAO dao) { if (entity instanceof TopiaEntityContextable) { - TopiaEntityContextable entityAbstract = (TopiaEntityContextable) entity; - if (entityAbstract.getTopiaContext() == null) { + TopiaEntityContextable topiaEntityContextable = (TopiaEntityContextable) entity; + if (topiaEntityContextable.getTopiaDAO() == null) { try { - entityAbstract.setTopiaContext(context); + topiaEntityContextable.setTopiaDAO(dao); } catch (TopiaException eee) { if (log.isWarnEnabled()) { log.warn("Impossible d'initialiser le TopiaContext" - + " sur cette entité : " + entityAbstract, + + " sur cette entité : " + topiaEntityContextable, eee); } } @@ -675,11 +674,12 @@ @Override public void onPostLoad(PostLoadEvent event) { - TopiaContextImplementor context = getContext(rootContext, event - .getSession()); - if (context != null && event.getEntity() instanceof TopiaEntity) { - attachContext(event.getEntity(), context); - context.getFiresSupport().fireOnPostLoad(context, +// TopiaContextImplementor context = getContext(rootContext, event +// .getSession()); + AbstractTopiaDAO dao = null; // TODO brendan 30/09/13 Implment + if (dao != null && event.getEntity() instanceof TopiaEntity) { + attachContext(event.getEntity(), dao); + dao.getTopiaFiresSupport().fireOnPostLoad(dao, (TopiaEntity) event.getEntity(), new Object[]{}); } } Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaUtil.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaUtil.java 2013-09-27 18:43:30 UTC (rev 2806) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaUtil.java 2013-10-01 13:15:11 UTC (rev 2807) @@ -24,6 +24,7 @@ */ package org.nuiton.topia.framework; +import com.google.common.base.Preconditions; import com.google.common.base.Supplier; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -49,7 +50,10 @@ import java.net.URL; import java.sql.Connection; import java.sql.SQLException; +import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; import java.util.Properties; import java.util.StringTokenizer; import java.util.regex.Pattern; @@ -481,6 +485,34 @@ return config.getProperty(TopiaContextFactory.CONFIG_DEFAULT_SCHEMA); } + public static Map<String, Object> convertPropertiesArrayToMap(Object... propertyNamesAndValues) throws IllegalArgumentException { + int propertiesLength = propertyNamesAndValues.length; + Preconditions.checkArgument(propertiesLength % 2 == 0, + "Wrong number of argument " + + propertiesLength + + ", you must have even number."); + Map<String, Object> properties = new LinkedHashMap<String, Object>(); + for (int i = 0; i < propertyNamesAndValues.length; ) { + Object aPropertyName = propertyNamesAndValues[i++]; + Object value = propertyNamesAndValues[i++]; + Preconditions.checkArgument( + aPropertyName instanceof String, + "Argument at position [" + (i - 1) + "] " + + "should be a property name (says a String) but was " + + aPropertyName); + properties.put((String) aPropertyName, value); + } + return properties; + } + + public static Map<String, Object> convertPropertiesArrayToMap( + String propertyName, Object propertyValue, Object... otherPropertyNamesAndValues) throws IllegalArgumentException { + Map<String, Object> properties = new HashMap<String, Object>(); + properties.put(propertyName, propertyValue); + properties.putAll(convertPropertiesArrayToMap(otherPropertyNamesAndValues)); + return properties; + } + public static class ConnectionProviderSupplier implements Supplier<ConnectionProvider>, Closeable { protected ServiceRegistry serviceRegistry; Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityDAOTransformer.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityDAOTransformer.java 2013-09-27 18:43:30 UTC (rev 2806) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityDAOTransformer.java 2013-10-01 13:15:11 UTC (rev 2807) @@ -637,30 +637,29 @@ body.append("" /*{ - { - List<<%=attrSimpleType%>> list = getTopiaContext() - .getDAO(<%=attrSimpleType%>.class) - .findAllByProperties(<%=attrSimpleType%>.<%=getConstantName(reverseAttrName)%>, entity); - for (<%=attrSimpleType%> item : list) { + { + List<<%=attrSimpleType%>> list = topiaDAOSupplier + .getDAO(<%=attrSimpleType%>.class) + .findAllByProperties(<%=attrSimpleType%>.<%=getConstantName(reverseAttrName)%>, entity); + for (<%=attrSimpleType%> item : list) { - // sletellier : Set null only if target is concerned by deletion - if (entity.equals(item.<%=getName%>())) { - item.<%=setName%>(null); - } - }*/ + // sletellier : Set null only if target is concerned by deletion + if (entity.equals(item.<%=getName%>())) { + item.<%=setName%>(null); + } + }*/ ); if (attr.isAggregate()) { body.append("" /*{ - getTopiaContext().getDAO(<%=attrSimpleType%>.class).delete(item); - //item.delete(); + topiaDAOSupplier.getDAO(<%=attrSimpleType%>.class).delete(item); }*/ ); } body.append("" /*{ - } - } + } + } }*/ ); @@ -672,7 +671,6 @@ ObjectModelOperation op; op = addOperation(result, "delete", "void", ObjectModelJavaModifier.PUBLIC); addAnnotation(result, op,Override.class); - addException(op, TopiaException.class); addParameter(op, "E", "entity"); body.append("" /*{ @@ -707,7 +705,6 @@ addParameter(operation, "Class<U>", "type"); addParameter(operation, "E", "entity"); - addException(operation, TopiaException.class); addAnnotation(result, operation, Override.class); setOperationBody(operation, "" /*{ @@ -721,7 +718,6 @@ ObjectModelJavaModifier.PUBLIC); addParameter(operation, "E", "entity"); - addException(operation, TopiaException.class); addAnnotation(result, operation, Override.class); setOperationBody(operation, "" /*{ @@ -750,7 +746,6 @@ addParameter(operation, "Class<U>", "type"); addParameter(operation, "E", "entity"); - addException(operation, TopiaException.class); addAnnotation(result, operation, Override.class); StringBuilder buffer = new StringBuilder(300); buffer.append("" @@ -810,7 +805,7 @@ /*{ if (type == <%=usageSimpleType%>.class) { <%=daoName%> dao = (<%=daoName%>) - getTopiaContext().getDAO(<%=usageSimpleType%>.class); + topiaDAOSupplier.getDAO(<%=usageSimpleType%>.class); tmp = dao.<%=methodName%>(entity); result.addAll(tmp); } @@ -832,7 +827,6 @@ ObjectModelJavaModifier.PUBLIC); addParameter(operation, "E", "entity"); - addException(operation, TopiaException.class); addAnnotation(result, operation, Override.class); buffer = new StringBuilder(300); @@ -887,7 +881,6 @@ for (ObjectModelOperation op : operations) { Set<String> exceptions = op.getExceptions(); - exceptions.add(TopiaException.class.getName()); cloneOperation(op, result, true, @@ -974,7 +967,6 @@ getJavaBeanMethodName("findBy", attrName), "E", ObjectModelJavaModifier.PUBLIC); - addException(op, TopiaException.class); addParameter(op, attrType, "v"); setOperationBody(op, "" /*{ @@ -987,7 +979,6 @@ getJavaBeanMethodName("findAllBy", attrName), "List<E>", ObjectModelJavaModifier.PUBLIC); - addException(op, TopiaException.class); addParameter(op, attrType, "v"); setOperationBody(op, "" /*{ @@ -1005,7 +996,6 @@ getJavaBeanMethodName("findBy", assocClassName), "E", ObjectModelJavaModifier.PUBLIC); - addException(op, TopiaException.class); addParameter(op, assocClassFQN, "value"); setOperationBody(op, "" /*{ @@ -1018,7 +1008,6 @@ getJavaBeanMethodName("findAllBy", assocClassName), "List<E>", ObjectModelJavaModifier.PUBLIC); - addException(op, TopiaException.class); addParameter(op, assocClassFQN, "value"); setOperationBody(op, "" /*{ @@ -1044,7 +1033,6 @@ getJavaBeanMethodName("findContains", attrName), "E", ObjectModelJavaModifier.PUBLIC); - addException(op, TopiaException.class); addParameter(op, attrType, "v"); setOperationBody(op, "" /*{ @@ -1057,7 +1045,6 @@ getJavaBeanMethodName("findAllContains", attrName), "List<E>", ObjectModelJavaModifier.PUBLIC); - addException(op, TopiaException.class); addParameter(op, attrType, "v"); setOperationBody(op, "" /*{ @@ -1114,11 +1101,9 @@ } ObjectModelOperation findByNaturalId = addOperation(result, "findByNaturalId", "E", ObjectModelJavaModifier.PUBLIC); - addException(findByNaturalId, TopiaException.class); ObjectModelOperation existByNaturalId = addOperation(result, "existByNaturalId", "boolean", ObjectModelJavaModifier.PUBLIC); - addException(existByNaturalId, TopiaException.class); // TODO sletellier 20120406 : remove method on 3.0 ObjectModelOperation create = addOperation(result, @@ -1127,13 +1112,10 @@ // sletellier : mark as Deprecated (http://nuiton.org/issues/2051) setDocumentation(create, "@deprecated since 2.6.10, prefer use {@link #createByNaturalId}\n"); addAnnotation(result, create, "Deprecated"); - addException(create, TopiaException.class); ObjectModelOperation createByNaturalId = addOperation(result, "createByNaturalId", "E", ObjectModelJavaModifier.PUBLIC); - addException(createByNaturalId, TopiaException.class); - // used for calling findByProperties in findByNaturalId String searchProperties = ""; // used for calling findByNaturalId in existByNaturalId @@ -1196,8 +1178,6 @@ ObjectModelOperation createByNotNull = addOperation(result, "createByNotNull", "E", ObjectModelJavaModifier.PUBLIC); - addException(createByNotNull, TopiaException.class); - String createProperties = ""; // String params = ""; String clazzName = clazz.getName(); Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/PersistenceContextTransformer.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/PersistenceContextTransformer.java 2013-09-27 18:43:30 UTC (rev 2806) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/PersistenceContextTransformer.java 2013-10-01 13:15:11 UTC (rev 2807) @@ -36,7 +36,6 @@ import org.nuiton.eugene.models.object.ObjectModelOperation; import org.nuiton.topia.AbstractTopiaPersistenceContext; import org.nuiton.topia.TopiaContext; -import org.nuiton.topia.TopiaException; import org.nuiton.topia.persistence.TopiaEntity; import org.nuiton.topia.persistence.util.EntityOperator; import org.nuiton.topia.persistence.util.EntityOperatorStore; @@ -183,10 +182,9 @@ // specialized getXXXDao method op = addOperation(output, "get" + daoClazzName, clazz.getPackageName() + '.' + daoClazzName); addImport(output, clazz); - addException(op, TopiaException.class); setOperationBody(op, "" /*{ - <%=daoClazzName%> result = context.getDAO(<%=clazzName%>.class, <%=daoClazzName%>.class); + <%=daoClazzName%> result = getDAO(<%=clazzName%>.class, <%=daoClazzName%>.class); return result; }*/ ); Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/TopiaGeneratorUtil.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/TopiaGeneratorUtil.java 2013-09-27 18:43:30 UTC (rev 2806) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/TopiaGeneratorUtil.java 2013-10-01 13:15:11 UTC (rev 2807) @@ -44,6 +44,7 @@ import org.nuiton.eugene.models.object.ObjectModelInterface; import org.nuiton.eugene.models.object.ObjectModelOperation; import org.nuiton.eugene.models.object.ObjectModelParameter; +import org.nuiton.topia.persistence.AbstractTopiaDAO; import org.nuiton.topia.persistence.TopiaDAOImpl; import java.util.ArrayList; @@ -981,7 +982,7 @@ if (StringUtils.isEmpty(daoImpl)) { // use the default dao implementation of topia - result = TopiaDAOImpl.class; + result = AbstractTopiaDAO.class; } else { try { result = Class.forName(daoImpl); Copied: trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/AbstractTopiaDAO.java (from rev 2804, trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaDAOImpl.java) =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/AbstractTopiaDAO.java (rev 0) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/AbstractTopiaDAO.java 2013-10-01 13:15:11 UTC (rev 2807) @@ -0,0 +1,1224 @@ +/* + * #%L + * ToPIA :: Persistence + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2004 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +/* * + * TopiaDAOAbstract.java + * + * Created: 31 déc. 2005 13:10:34 + * + * @author poussin <poussin@codelutin.com> + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ + +package org.nuiton.topia.persistence; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.hibernate.HibernateException; +import org.hibernate.metadata.ClassMetadata; +import org.nuiton.topia.TopiaContext; +import org.nuiton.topia.TopiaDAOSupplier; +import org.nuiton.topia.TopiaException; +import org.nuiton.topia.TopiaHibernateSupport; +import org.nuiton.topia.TopiaJpaSupport; +import org.nuiton.topia.TopiaListenableSupport; +import org.nuiton.topia.TopiaSqlSupport; +import org.nuiton.topia.event.TopiaEntityListener; +import org.nuiton.topia.event.TopiaEntityVetoable; +import org.nuiton.topia.framework.TopiaContextImplementor; +import org.nuiton.topia.framework.TopiaFiresSupport; +import org.nuiton.topia.framework.TopiaUtil; +import org.nuiton.topia.persistence.pager.TopiaPagerBean; +import org.nuiton.util.PagerBeanUtil; + +import java.lang.reflect.InvocationTargetException; +import java.security.Permission; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; + +/** + * Cette classe permet d'avoir un ensemble de méthode implantée de façon + * standard et plus spécifiquement pour Hibernate. + * <p/> + * Certains accès à Hibernate sont tout de même fait ici, car on a pris le choix + * de se baser entièrement sur hibernate pour la persistence, et il est ainsi + * possible d'accèder au meta information hibernate sur les classes lorque l'on + * en a besoin. + * + * @param <E> le type de l'entite + * @author bpoussin <poussin@codelutin.com> + * @version $Id$ + */ + +public abstract class AbstractTopiaDAO<E extends TopiaEntity> implements TopiaDAO<E> { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + private static Log log = LogFactory.getLog(AbstractTopiaDAO.class); + + /** + * Default batch size used to iterate on data. + * + * @since 2.6.14 + */ + protected int batchSize = 1000; + + protected TopiaHibernateSupport topiaHibernateSupport; + + protected TopiaJpaSupport topiaJpaSupport; + + protected TopiaSqlSupport topiaSqlSupport; + + protected TopiaListenableSupport topiaListenableSupport; + + protected TopiaIdFactory topiaIdFactory; + + protected TopiaFiresSupport topiaFiresSupport; + + protected TopiaDAOSupplier topiaDAOSupplier; + + public abstract TopiaEntityEnum getTopiaEntityEnum(); + + public abstract Class<E> getEntityClass(); + + public Iterator<E> iterator() { + + Iterator<E> iterator = new FindAllIterator<E, E>( + this, + getEntityClass(), + batchSize, + "FROM " + getTopiaEntityEnum().getImplementationFQN() + " ORDER BY id", + Collections. <String, Object> emptyMap()); + + return iterator; + + } + +// /** +// * Retourne l'id de l'entity +// * +// * @param e l'entity +// * @return l'id de l'entity ou null si pas trouvé +// * @throws org.nuiton.topia.TopiaException Si une erreur survient durant la recherche +// */ +// protected Serializable getId(E e) { +// ClassMetadata meta = getClassMetadata(); +// String idPropName = meta.getIdentifierPropertyName(); +// +// try { +// Serializable result; +// result = (Serializable) PropertyUtils.getSimpleProperty(e, +// idPropName); +// return result; +// } catch (Exception eee) { +// throw new TopiaException("Impossible de récuperer l'identifiant " +// + idPropName + " de l'entite: " + e); +// } +// } + +// /** +// * Retourne l'id de l'entity representer comme une map +// * +// * @param map l'entity en representation map +// * @return l'id de l'entity ou null si pas trouvé +// * @throws org.nuiton.topia.TopiaException Si une erreur survient durant la recherche +// */ +// protected Serializable getId(Map map) { +// try { +// ClassMetadata meta = getClassMetadata(); +// String idPropName = meta.getIdentifierPropertyName(); +// +// Serializable id = (Serializable) map.get(idPropName); +// return id; +// } catch (HibernateException eee) { +// throw new TopiaException(eee); +// } +// } + + /** + * When AbstractTopiaContext create the TopiaDAOHibernate, it must call this + * method just after. + */ + public void init( + TopiaHibernateSupport topiaHibernateSupport, + TopiaJpaSupport topiaJpaSupport, + TopiaSqlSupport topiaSqlSupport, + TopiaListenableSupport topiaListenableSupport, + TopiaIdFactory topiaIdFactory, + TopiaFiresSupport topiaFiresSupport, + TopiaDAOSupplier topiaDAOSupplier) { + log.debug("init dao for " + getEntityClass()); + this.topiaHibernateSupport = topiaHibernateSupport; + this.topiaJpaSupport = topiaJpaSupport; + this.topiaSqlSupport = topiaSqlSupport; + this.topiaListenableSupport = topiaListenableSupport; + this.topiaIdFactory = topiaIdFactory; + this.topiaFiresSupport = topiaFiresSupport; + this.topiaDAOSupplier = topiaDAOSupplier; + } + + public TopiaFiresSupport getTopiaFiresSupport() { + return topiaFiresSupport; + } + + @Override + public int getBatchSize() { + return batchSize; + } + + @Override + public void setBatchSize(int batchSize) { + this.batchSize = batchSize; + } + + protected String createSimpleQuery() { + return createSimpleQuery0(null); + } + + protected String createSimpleQuery0(String alias) { + String hql = "from " + getTopiaEntityEnum().getImplementationFQN(); + if (StringUtils.isNotBlank(alias)) { + hql += " " + alias; + } + return hql; + } + + @Deprecated + public String createSimpleQuery(String alias) { + return createSimpleQuery0(alias); + } + + public E newInstance() { + if (log.isTraceEnabled()) { + log.trace("entityClass = " + getEntityClass()); + } + Class<E> implementation = (Class<E>) + getTopiaEntityEnum().getImplementation(); + try { + E newInstance = implementation.newInstance(); + return newInstance; + } catch (InstantiationException e) { + throw new TopiaException( + "Impossible de trouver ou d'instancier la classe " + + implementation); + } catch (IllegalAccessException e) { + throw new TopiaException( + "Impossible de trouver ou d'instancier la classe " + + implementation); + } + } + + public void addTopiaEntityListener(TopiaEntityListener listener) { + topiaListenableSupport.addTopiaEntityListener(getEntityClass(), listener); + } + + public void addTopiaEntityVetoable(TopiaEntityVetoable vetoable) { + topiaListenableSupport.addTopiaEntityVetoable(getEntityClass(), vetoable); + } + + public void removeTopiaEntityListener(TopiaEntityListener listener) { + topiaListenableSupport.removeTopiaEntityListener(getEntityClass(), listener); + } + + public void removeTopiaEntityVetoable(TopiaEntityVetoable vetoable) { + topiaListenableSupport.removeTopiaEntityVetoable(getEntityClass(), vetoable); + } + + public E create(E entity) { + try { + // first set topiaId + if (StringUtils.isBlank(entity.getTopiaId())) { + + // only set id if not already on + String topiaId = topiaIdFactory.newTopiaId(getEntityClass(), entity); + entity.setTopiaId(topiaId); + } + + if (entity instanceof TopiaEntityContextable) { + TopiaEntityContextable contextable = (TopiaEntityContextable) entity; + contextable.setTopiaDAO(this); + } + + // save entity + topiaHibernateSupport.getHibernateSession().save(entity); + topiaFiresSupport.warnOnCreateEntity(entity); + return entity; + } catch (HibernateException eee) { + throw new TopiaException(eee); + } + } + + public E create(String propertyName, Object propertyValue, Object... otherPropertyNamesAndValues) { + Map<String, Object> properties = + TopiaUtil.convertPropertiesArrayToMap(propertyName, propertyValue, otherPropertyNamesAndValues); + E result = create(properties); + return result; + } + + @Override + public E create(Object... propertyNamesAndValues) { + Map<String, Object> properties = TopiaUtil.convertPropertiesArrayToMap(propertyNamesAndValues); + E result = create(properties); + return result; + } + + /** + * Cette methode appelle fireVetoableCreate et fireOnCreated Si vous la + * surchargé, faites attention a appeler le super ou a appeler vous aussi + * ces deux methodes. + */ + + public E create(Map<String, Object> properties) { + + E result = newInstance(); + + try { + for (Map.Entry<String, Object> e : properties.entrySet()) { + String propertyName = e.getKey(); + Object value = e.getValue(); + PropertyUtils.setProperty(result, propertyName, value); + } + } catch (IllegalAccessException eee) { + throw new IllegalArgumentException( + "Can't put properties on new Object", eee); + } catch (InvocationTargetException eee) { + throw new IllegalArgumentException( + "Can't put properties on new Object", eee); + } catch (NoSuchMethodException eee) { + throw new IllegalArgumentException( + "Can't put properties on new Object", eee); + } + + create(result); + + return result; + } + + + public E update(E e) { + try { + topiaHibernateSupport.getHibernateSession().saveOrUpdate(e); + topiaFiresSupport.warnOnUpdateEntity(e); + return e; + } catch (HibernateException eee) { + throw new TopiaException(eee); + } + } + + + public void delete(E e) { + try { + topiaHibernateSupport.getHibernateSession().delete(e); + e.notifyDeleted(); + topiaFiresSupport.warnOnDeleteEntity(e); + } catch (HibernateException eee) { + throw new TopiaException(eee); + } + } + + + public void deleteAll(Iterable<E> entities) { + for (E entity : entities) { + delete(entity); + } + } + + protected HqlAndParametersBuilder<E> getHqlForProperties(String propertyName, + Object propertyValue, + Object... otherPropertyNamesAndValues) { + Map<String, Object> properties = + TopiaUtil.convertPropertiesArrayToMap(propertyName, propertyValue, otherPropertyNamesAndValues); + return getHqlForProperties(properties); + } + + protected HqlAndParametersBuilder<E> getHqlForNoConstraint() { + Map<String, Object> properties = Collections.emptyMap(); + return getHqlForProperties(properties); + } + + protected HqlAndParametersBuilder<E> getHqlForProperties(Map<String, Object> properties) { + HqlAndParametersBuilder<E> hqlAndParametersBuilder = new HqlAndParametersBuilder<E>(getEntityClass()); + for (Map.Entry<String, Object> property : properties.entrySet()) { + hqlAndParametersBuilder.addEquals(property.getKey(), property.getValue()); + } + return hqlAndParametersBuilder; + } + + protected TopiaQueryBuilderRunQueryStep<E> forHql(String hql) { + Map<String, Object> properties = Collections.emptyMap(); + return forHql(hql, properties); + } + + protected TopiaQueryBuilderRunQueryStep<E> forHql(String hql, Map<String, Object> hqlParameters) { + return new TopiaQueryBuilderRunQueryStep(this, hql, hqlParameters); + } + + protected TopiaQueryBuilderRunQueryStep<E> forHql(String hql, String parameterName, + Object parameterValue, + Object... otherParameterNamesAndValues) { + Map<String, Object> hqlParameters = + TopiaUtil.convertPropertiesArrayToMap(parameterName, parameterValue, otherParameterNamesAndValues); + return forHql(hql, hqlParameters); + } + + public TopiaQueryBuilderCreateQueryStep<E> newQueryBuilder() { + return new TopiaQueryBuilderCreateQueryStep(this); + } + + // shortcuts for first step of builder + + public TopiaQueryBuilderAddCriteriaStep<E> forProperties(Map<String, Object> properties) { + return newQueryBuilder().forProperties(properties); + } + + public TopiaQueryBuilderAddCriteriaStep<E> forProperties(String propertyName, + Object propertyValue, + Object... otherPropertyNamesAndValues) { + return newQueryBuilder().forProperties(propertyName, propertyValue, otherPropertyNamesAndValues); + } + + public TopiaQueryBuilderAddCriteriaStep<E> forAll() { + return newQueryBuilder().forAll(); + } + + public static class TopiaQueryBuilderCreateQueryStep<E extends TopiaEntity> { + + protected AbstractTopiaDAO<E> topiaDAO; + + protected TopiaQueryBuilderCreateQueryStep(AbstractTopiaDAO<E> topiaDAO) { + this.topiaDAO = topiaDAO; + } + + public TopiaQueryBuilderAddCriteriaStep<E> forProperties(Map<String, Object> properties) { + HqlAndParametersBuilder<E> hqlAndParametersBuilder = topiaDAO.getHqlForProperties(properties); + return getNextStep(hqlAndParametersBuilder); + } + + public TopiaQueryBuilderAddCriteriaStep<E> forProperties(String propertyName, + Object propertyValue, + Object... otherPropertyNamesAndValues) { + HqlAndParametersBuilder<E> hqlAndParametersBuilder = topiaDAO.getHqlForProperties(propertyName, propertyValue, otherPropertyNamesAndValues); + return getNextStep(hqlAndParametersBuilder); + } + + public TopiaQueryBuilderAddCriteriaStep<E> forAll() { + HqlAndParametersBuilder<E> hqlAndParametersBuilder = topiaDAO.getHqlForNoConstraint(); + return getNextStep(hqlAndParametersBuilder); + } + + protected TopiaQueryBuilderAddCriteriaStep<E> getNextStep(HqlAndParametersBuilder<E> hqlAndParametersBuilder) { + TopiaQueryBuilderAddCriteriaStep nextStep = new TopiaQueryBuilderAddCriteriaStep(topiaDAO, hqlAndParametersBuilder); + return nextStep; + } + + // shortcuts to next step + + public TopiaQueryBuilderAddCriteriaStep<E> addEquals(String property, Object value) { + return forAll().addEquals(property, value); + } + + public TopiaQueryBuilderAddCriteriaStep<E> addIn(String property, Iterable<Object> values) { + return forAll().addIn(property, values); + } + + public TopiaQueryBuilderAddCriteriaStep<E> addContains(String property, Object value) { + return forAll().addContains(property, value); + } + + public TopiaQueryBuilderAddCriteriaStep<E> addNull(String property) { + return forAll().addNull(property); + } + + public TopiaQueryBuilderRunQueryStep<E> setOrderByArguments(Set<String> orderByArguments) { + return forAll().setOrderByArguments(orderByArguments); + } + + public TopiaQueryBuilderRunQueryStep<E> setOrderByArguments(String... orderByArguments) { + return forAll().setOrderByArguments(orderByArguments); + } + + } + + public static class TopiaQueryBuilderAddCriteriaStep<E extends TopiaEntity> { + + protected AbstractTopiaDAO<E> topiaDAO; + + protected HqlAndParametersBuilder<E> hqlAndParametersBuilder; + + protected boolean hasOrderByClause = false; + + protected TopiaQueryBuilderAddCriteriaStep(AbstractTopiaDAO<E> topiaDAO, HqlAndParametersBuilder<E> hqlAndParametersBuilder) { + this.topiaDAO = topiaDAO; + this.hqlAndParametersBuilder = hqlAndParametersBuilder; + } + + public TopiaQueryBuilderRunQueryStep<E> setOrderByArguments(Set<String> orderByArguments) { + hasOrderByClause = ! Iterables.isEmpty(orderByArguments); + hqlAndParametersBuilder.setOrderByArguments(orderByArguments); + return getNextStep(); + } + + public TopiaQueryBuilderRunQueryStep<E> setOrderByArguments(String... orderByArguments) { + hqlAndParametersBuilder.setOrderByArguments(orderByArguments); + return getNextStep(); + } + + public TopiaQueryBuilderAddCriteriaStep<E> addEquals(String property, Object value) { + hqlAndParametersBuilder.addEquals(property, value); + return this; + } + + public TopiaQueryBuilderAddCriteriaStep<E> addIn(String property, Iterable<Object> values) { + hqlAndParametersBuilder.addIn(property, values); + return this; + } + + public TopiaQueryBuilderAddCriteriaStep<E> addContains(String property, Object value) { + hqlAndParametersBuilder.addContains(property, value); + return this; + } + + public TopiaQueryBuilderAddCriteriaStep<E> addNull(String property) { + hqlAndParametersBuilder.addNull(property); + return this; + } + + // shortcuts to next step + + public boolean exists() { + return getNextStep().exists(); + } + + public E findAnyOrNull() { + return getNextStep().findAnyOrNull(); + } + + public E findUniqueOrNull() { + return getNextStep().findUniqueOrNull(); + } + + public E findAny() { + return getNextStep().findAny(); + } + + public E findUnique() { + return getNextStep().findUnique(); + } + + public E findFirst() { + return getNextStep().findFirst(); + } + + public E findFirstOrNull() { + return getNextStep().findFirstOrNull(); + } + + public List<E> findAll() { + return getNextStep().findAll(); + } + + public List<E> findAll(int startIndex, int endIndex) { + return getNextStep().findAll(startIndex, endIndex); + } + + public Iterable<E> findAllLazy() { + return getNextStep().findAllLazy(); + } + + public long count() { + return getNextStep().count(); + } + + public List<String> findAllIds(int startIndex, int endIndex) { + return getNextStep().findAllIds(startIndex, endIndex); + } + + public List<String> findAllIds() { + return getNextStep().findAllIds(); + } + + protected TopiaQueryBuilderRunQueryStep<E> getNextStep() { + String hql = hqlAndParametersBuilder.getHql(); + Map<String, Object> hqlParameters = hqlAndParametersBuilder.getHqlParameters(); + TopiaQueryBuilderRunQueryStep nextStep = new TopiaQueryBuilderRunQueryStep(topiaDAO, hql, hqlParameters); + return nextStep; + } + + } + + public static class TopiaQueryBuilderRunQueryStep<E extends TopiaEntity> { + + protected final String hql; + + protected final Map<String, Object> hqlParameters; + + protected AbstractTopiaDAO<E> topiaDAO; + + protected TopiaQueryBuilderRunQueryStep(AbstractTopiaDAO<E> topiaDAO, String hql, Map<String, Object> hqlParameters) { + this.hql = hql; + this.hqlParameters = hqlParameters; + this.topiaDAO = topiaDAO; + } + + public boolean exists() { + return topiaDAO.exists(hql, hqlParameters); + } + + public long count() { + String hqlWithSelectClause = "select count(topiaId) " + hql; + return topiaDAO.count(hqlWithSelectClause, hqlParameters); + } + + public E findUnique() { + return topiaDAO.findUnique(hql, hqlParameters); + } + + public E findUniqueOrNull() { + return topiaDAO.findUniqueOrNull(hql, hqlParameters); + } + + public E findFirst() { + return topiaDAO.findFirst(hql, hqlParameters); + } + + public E findFirstOrNull() { + return topiaDAO.findFirstOrNull(hql, hqlParameters); + } + + public E findAny() { + return topiaDAO.findAny(hql, hqlParameters); + } + + public E findAnyOrNull() { + return topiaDAO.findAnyOrNull(hql, hqlParameters); + } + + public List<E> findAll() { + return topiaDAO.findAll(hql, hqlParameters); + } + + public Iterable<E> findAllLazy() { + return topiaDAO.findAllLazy(hql, hqlParameters); + } + + public List<E> findAll(int startIndex, int endIndex) { + return topiaDAO.findAll(hql, hqlParameters, startIndex, endIndex); + } + + public List<String> findAllIds() { + // XXX brendan 30/09/13 does this truely work ? + String hqlWithSelectClause = "select topiaId " + hql; + return topiaDAO.findAll(hqlWithSelectClause, hqlParameters, String.class); + } + + public List<String> findAllIds(int startIndex, int endIndex) { + // XXX brendan 30/09/13 does this truely work ? + String hqlWithSelectClause = "select topiaId " + hql; + return topiaDAO.findAll(hqlWithSelectClause, hqlParameters, String.class, startIndex, endIndex); + } + + } + + protected boolean exists(String hql, Map<String, Object> hqlParameters) { + List<E> entities = topiaJpaSupport.find(hql, 0, 0, hqlParameters); + boolean exists = !entities.isEmpty(); + return exists; + } + + protected long count(String hql, Map<String, Object> hqlParameters) { + Preconditions.checkArgument(hql.toLowerCase().trim().startsWith("select count(")); + Long count = findUnique(hql, hqlParameters, Long.class); + return count; + } + + protected E findUnique(String hql, Map<String, Object> hqlParameters) { + E unique = findUnique(hql, hqlParameters, getEntityClass()); + return unique; + } + + protected E findUniqueOrNull(String hql, Map<String, Object> hqlParameters) { + E uniqueOrNull = findUniqueOrNull(hql, hqlParameters, getEntityClass()); + return uniqueOrNull; + } + + protected E findFirst(String hql, Map<String, Object> hqlParameters) { + E firstOrNull = findFirst(hql, hqlParameters, getEntityClass()); + return firstOrNull; + } + + protected E findFirstOrNull(String hql, Map<String, Object> hqlParameters) { + E anyOrNull = findFirstOrNull(hql, hqlParameters, getEntityClass()); + return anyOrNull; + } + + protected E findAny(String hql, Map<String, Object> hqlParameters) { + E anyOrNull = findAny(hql, hqlParameters, getEntityClass()); + return anyOrNull; + } + + protected E findAnyOrNull(String hql, Map<String, Object> hqlParameters) { + E anyOrNull = findAnyOrNull(hql, hqlParameters, getEntityClass()); + return anyOrNull; + } + + protected <R> R findUnique(String hql, Map<String, Object> hqlParameters, Class<R> type) { + R uniqueOrNull = findUniqueOrNull(hql, hqlParameters, type); + if (uniqueOrNull == null) { + // TODO brendan 30/09/13 throw another exception if no result + throw new TopiaException("query " + hql + " returns no elements"); + } + return uniqueOrNull; + } + + protected <R> R findUniqueOrNull(String hql, Map<String, Object> hqlParameters, Class<R> type) { + List<R> results = findAll(hql, hqlParameters, type, 0, 1); + // If there is more than 1 result, throw an exception + if (results.size() > 1) { + String message = String.format( + "The query '%s' returns more than 1 unique result", hql); + // TODO AThimel 02/08/13 Throw another exception if more than 1 result is found + throw new TopiaException(message); + } + // otherwise return the first one, or null + R uniqueOrNull = Iterables.getOnlyElement(results, null); + return uniqueOrNull; + } + + protected <R> R findFirst(String hql, Map<String, Object> hqlParameters, Class<R> type) { + R firstOrNull = findFirstOrNull(hql, hqlParameters, type); + if (firstOrNull == null) { + // TODO brendan 30/09/13 throw another exception if no result + throw new TopiaException("query " + hql + " returns no elements"); + } + return firstOrNull; + } + + protected <R> R findFirstOrNull(String hql, Map<String, Object> hqlParameters, Class<R> type) { + Preconditions.checkArgument(hql.toLowerCase().contains("order by")); + R anyOrNull = findAnyOrNull(hql, hqlParameters, type); + return anyOrNull; + } + + protected <R> R findAny(String hql, Map<String, Object> hqlParameters, Class<R> type) { + R anyOrNull = findAnyOrNull(hql, hqlParameters, type); + if (anyOrNull == null) { + // TODO brendan 30/09/13 throw another exception if no result + throw new TopiaException("query " + hql + " returns no elements"); + } + return anyOrNull; + } + + protected <R> R findAnyOrNull(String hql, Map<String, Object> hqlParameters, Class<R> type) { + Preconditions.checkNotNull(hql); + Preconditions.checkNotNull(hqlParameters); + List<R> results = findAll(hql, hqlParameters, type, 0, 0); + R anyOrNull = Iterables.getOnlyElement(results, null); + return anyOrNull; + } + + protected List<E> findAll(String hql, Map<String, Object> hqlParameters) { + Preconditions.checkNotNull(hql); + Preconditions.checkNotNull(hqlParameters); + List<E> all = topiaJpaSupport.findAll(hql, hqlParameters); + return all; + } + + protected <R> List<R> findAll(String hql, Map<String, Object> hqlParameters, Class<R> type) { + Preconditions.checkNotNull(hql); + Preconditions.checkNotNull(hqlParameters); + Preconditions.checkNotNull(type); + List<R> all = topiaJpaSupport.findAll(hql, hqlParameters); + return all; + } + + protected List<E> findAll(String hql, Map<String, Object> hqlParameters, int startIndex, int endIndex) { + Preconditions.checkNotNull(hql); + Preconditions.checkNotNull(hqlParameters); + List<E> all = topiaJpaSupport.find(hql, startIndex, endIndex, hqlParameters); + return all; + } + + protected <R> List<R> findAll(String hql, Map<String, Object> hqlParameters, Class<R> type, int startIndex, int endIndex) { + Preconditions.checkNotNull(hql); + Preconditions.checkNotNull(hqlParameters); + Preconditions.checkNotNull(type); + List<R> all = topiaJpaSupport.find(hql, startIndex, endIndex, hqlParameters); + return all; + } + + protected <R> List<R> findAll(String hql, Map<String, Object> hqlParameters, Class<R> type, TopiaPagerBean pager) { + Preconditions.checkNotNull(hql); + Preconditions.checkNotNull(hqlParameters); + Preconditions.checkNotNull(type); + Preconditions.checkNotNull(pager); + + if (StringUtils.isNotBlank(pager.getSortColumn())) { + hql += " order by " + pager.getSortColumn(); + if (!pager.isSortAscendant()) { + hql += " desc"; + } + } + + List<R> result = topiaJpaSupport.find( + hql, + (int) pager.getRecordStartIndex(), + (int) pager.getRecordEndIndex() - 1, + hqlParameters); + + return result; + + } + + protected Iterable<E> findAllLazy(String hql, Map<String, Object> hqlParameters) { + + Preconditions.checkNotNull(hql); + Preconditions.checkNotNull(hqlParameters); + + final Iterator<E> iterator = new FindAllIterator<E, E>(this, + getEntityClass(), + batchSize, + hql, + hqlParameters); + Iterable<E> result = new Iterable<E>() { + @Override + public Iterator<E> iterator() { + return iterator; + } + }; + return result; + } + + protected <R> Iterable<R> findAllLazy(String hql, Map<String, Object> hqlParameters, Class<R> type) { + + Preconditions.checkNotNull(hql); + Preconditions.checkNotNull(hqlParameters); + Preconditions.checkNotNull(type); + + final Iterator<R> iterator = new FindAllIterator<E, R>(this, + type, + batchSize, + hql, + hqlParameters); + Iterable<R> result = new Iterable<R>() { + @Override + public Iterator<R> iterator() { + return iterator; + } + }; + return result; + } + + public TopiaQueryBuilderRunQueryStep<E> byTopiaId(String topiaId) { + Preconditions.checkNotNull(topiaId, "given topiaId is null"); + return newQueryBuilder().forProperties(TopiaEntity.PROPERTY_TOPIA_ID, topiaId).getNextStep(); + } + + @Deprecated + public E findByTopiaId(String id) { + return byTopiaId(id).findUniqueOrNull(); + } + + @Deprecated + public E findByProperty(String propertyName, Object value) { + return newQueryBuilder().forProperties(propertyName, value).findUniqueOrNull(); + } + + @Override + public <R> R findByQuery(Class<R> type, String hql, Object... propertyNamesAndValues) throws TopiaException { + Map<String, Object> properties = TopiaUtil.convertPropertiesArrayToMap(propertyNamesAndValues); + return findAny(hql, properties, type); + } + + @Override + public E findByPrimaryKey(Map<String, Object> keys) throws TopiaException { + return newQueryBuilder().forProperties(keys).findAnyOrNull(); + } + + @Override + @Deprecated + public E findByPrimaryKey(Object... propertyNamesAndValues) { + Map<String, Object> properties = TopiaUtil.convertPropertiesArrayToMap(propertyNamesAndValues); + E byPrimaryKey = findByPrimaryKey(properties); + return byPrimaryKey; + } + + @Override + public List<E> findAllWithOrder(String... propertyNames) { + return newQueryBuilder().forAll().setOrderByArguments(propertyNames).findAll(); + } + + @Override + public <R> List<R> findAllByQuery(Class<R> type, String hql, Object... propertyNamesAndValues) { + Map<String, Object> hqlParameters = TopiaUtil.convertPropertiesArrayToMap(propertyNamesAndValues); + List<R> all = findAll(hql, hqlParameters, type); + return all; + } + + @Deprecated + public E findByProperties(String propertyName, Object value, + Object... propertyNamesAndValues) { + return newQueryBuilder().forProperties(propertyName, value, propertyNamesAndValues).findUniqueOrNull(); + } + + @Deprecated + public E findByProperties(Map<String, Object> properties) { + return newQueryBuilder().forProperties(properties).findUniqueOrNull(); + } + + public List<E> findAll() { + return newQueryBuilder().forAll().findAll(); + } + + public List<String> findAllIds() { + List<String> find = newQueryBuilder().forAll().findAllIds(); + return find; + } + + @Deprecated + public List<E> findAllByProperty(String propertyName, Object value) { + List<E> all = newQueryBuilder().forProperties(propertyName, value).findAll(); + return all; + } + + @Deprecated + public List<E> findAllByProperties(String propertyName, Object value, Object... propertyNamesAndValues) { + List<E> all = newQueryBuilder().forProperties(propertyName, value, propertyNamesAndValues).findAll(); + return all; + } + + @Deprecated + public List<E> findAllByProperties(Map<String, Object> properties) { + List<E> all = newQueryBuilder().forProperties(properties).findAll(); + return all; + } + + + public E findContains(String propertyName, Object value) { + E find = newQueryBuilder().forAll().addContains(propertyName, value).findAny(); + return find; + } + + + public List<E> findAllContains(String propertyName, + Object value) { + List<E> find = newQueryBuilder().forAll().addContains(propertyName, value).findAll(); + return find; + } + + @Deprecated + public boolean existByTopiaId(String topiaId) { + boolean exists = byTopiaId(topiaId).exists(); + return exists; + } + + @Deprecated + public boolean existByProperties(String propertyName, Object propertyValue, + Object... propertyNamesAndValues) { + boolean exists = newQueryBuilder().forProperties(propertyName, propertyValue, propertyNamesAndValues).exists(); + return exists; + } + + public long count() { + long count = newQueryBuilder().forAll().count(); + return count; + } + + + @Deprecated + public boolean existsByQuery(String hql, Object... propertyNamesAndValues) { + Map<String, Object> hqlParameters = TopiaUtil.convertPropertiesArrayToMap(propertyNamesAndValues); + boolean exists = exists(hql, hqlParameters); + return exists; + } + + + @Deprecated + public long countByQuery(String hql, + Object... propertyNamesAndValues) { + + Preconditions.checkNotNull(StringUtils.isNotBlank(hql)); + Preconditions.checkArgument(hql.toUpperCase().trim().startsWith("SELECT COUNT(")); + Map<String, Object> hqlParameters = TopiaUtil.convertPropertiesArrayToMap(propertyNamesAndValues); + long count = forHql(hql, hqlParameters).count(); + return count; + } + + + @Deprecated + public E findByQuery(String hql, + Object... propertyNamesAndValues) { + Map<String, Object> hqlParameters = TopiaUtil.convertPropertiesArrayToMap(propertyNamesAndValues); + E uniqueOrNull = forHql(hql, hqlParameters).findUniqueOrNull(); + return uniqueOrNull; + } + + + @Deprecated + public List<E> findAllByQuery(String hql, + Object... propertyNamesAndValues) { + Map<String, Object> hqlParameters = TopiaUtil.convertPropertiesArrayToMap(propertyNamesAndValues); + List<E> all = forHql(hql, hqlParameters).findAll(); + return all; + } + + + @Deprecated + public Iterable<E> findAllLazyByQuery(String hql, + Object... propertyNamesAndValues) { + Map<String, Object> hqlParameters = TopiaUtil.convertPropertiesArrayToMap(propertyNamesAndValues); + Iterable<E> result = findAllLazy(hql, hqlParameters); + return result; + } + + + @Deprecated + public <R> Iterable<R> findAllLazyByQuery(Class<R> type, + String hql, + Object... propertyNamesAndValues) { + Map<String, Object> hqlParameters = TopiaUtil.convertPropertiesArrayToMap(propertyNamesAndValues); + Iterable<R> result = findAllLazy(hql, hqlParameters, type); + return result; + } + + + @Deprecated + public Iterable<E> findAllLazyByQuery(int batchSize, + String hql, + Object... propertyNamesAndValues) { + return findAllLazyByQuery(getEntityClass(), batchSize, hql, propertyNamesAndValues); + } + + + /** + * @deprecated use {@link #findAllLazy(String, java.util.Map, Class)} + */ + @Deprecated + public <R> Iterable<R> findAllLazyByQuery(Class<R> type, + int batchSize, + String hql, + Object... propertyNamesAndValues) { + setBatchSize(batchSize); + Map<String, Object> hqlParameters = TopiaUtil.convertPropertiesArrayToMap(propertyNamesAndValues); + Iterable<R> allLazy = findAllLazy(hql, hqlParameters, type); + return allLazy; + } + + + @Deprecated + public <R> List<R> findAllByQueryWithBound(Class<R> type, + String hql, + int startIndex, + int endIndex, + Object... propertyNamesAndValues) { + Map<String, Object> hqlParameters = TopiaUtil.convertPropertiesArrayToMap(propertyNamesAndValues); + List<R> all = findAll(hql, hqlParameters, type, startIndex, endIndex); + return all; + } + + + @Deprecated + public List<E> findAllByQueryWithBound(String hql, + int startIndex, + int endIndex, + Object... propertyNamesAndValues) { + List<E> result = findAllByQueryWithBound(getEntityClass(), + hql, + startIndex, + endIndex, + propertyNamesAndValues); + return result; + } + + + @Deprecated + public <R> List<R> findAllByQueryAndPager(Class<R> type, + String hql, + TopiaPagerBean pager, + Object... propertyNamesAndValues) { + Preconditions.checkNotNull(pager); + Preconditions.checkNotNull(hql); + + if (StringUtils.isNotBlank(pager.getSortColumn())) { + hql += " ORDER BY " + pager.getSortColumn(); + if (!pager.isSortAscendant()) { + hql += " DESC"; + } + } + List<R> result = findAllByQueryWithBound(type, hql, + (int) pager.getRecordStartIndex(), + (int) pager.getRecordEndIndex() - 1, + propertyNamesAndValues); + return result; + } + + + @Deprecated + public List<E> findAllByQueryAndPager(String hql, + TopiaPagerBean pager, + Object... propertyNamesAndValues) { + + List<E> result = findAllByQueryAndPager(getEntityClass(), + hql, + pager, + propertyNamesAndValues); + return result; + } + + + public void computeAndAddRecordsToPager(String hql, + TopiaPagerBean pager, + Object... propertyNamesAndValues) { + + long records = countByQuery(hql, propertyNamesAndValues); + + pager.setRecords(records); + PagerBeanUtil.computeRecordIndexesAndPagesNumber(pager); + } + + /** + * package locale method because this is hibernate specific method and + * we don't want expose it. + * + * @return the meta-data of the entity + * @throws org.nuiton.topia.TopiaException if any pb + */ + protected ClassMetadata getClassMetadata() { + ClassMetadata meta = topiaHibernateSupport.getHibernateFactory() + .getClassMetadata(getEntityClass()); + if (meta == null) { + meta = topiaHibernateSupport.getHibernateFactory().getClassMetadata( + getTopiaEntityEnum().getImplementationFQN()); + } + return meta; + } + + public static class FindAllIterator<E extends TopiaEntity, R> implements Iterator<R> { + + protected Iterator<R> data; + + protected final AbstractTopiaDAO<E> dao; + + protected final Class<R> type; + + protected final String hql; + + protected final Map<String, Object> params; + + protected TopiaPagerBean pager; + + public FindAllIterator(AbstractTopiaDAO<E> dao, + Class<R> type, + int batchSize, + String hql, + Map<String, Object> params) { + this.dao = dao; + this.type = type; + this.hql = hql; + this.params = params; + + String hql2 = hql.toLowerCase(); + int i = hql2.indexOf("order by"); + if (i == -1) { + throw new IllegalStateException( + "must have a *order by* in hql, " + + "but did not find it in " + hql); + } + + // get the count (removing the order-by) + long count2 = dao.countByQuery("SELECT COUNT(*) " + + hql.substring(0, i), params); + pager = new TopiaPagerBean(); + pager.setRecords(count2); + pager.setPageSize(batchSize); + PagerBeanUtil.computeRecordIndexesAndPagesNumber(pager); + + // empty iterator (will be changed at first next call) + data = Iterators.emptyIterator(); + } + + + public boolean hasNext() { + boolean result = data.hasNext() || // no more data + pager.getPageIndex() < pager.getPagesNumber(); + return result; + } + + + public R next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + + if (!data.hasNext()) { + + // must load iterator + + // increments page index + pager.setPageIndex(pager.getPageIndex() + 1); + PagerBeanUtil.computeRecordIndexesAndPagesNumber(pager); + + // load new window of data + data = dao.findAll(hql, params, type, pager).iterator(); + + } + + R next = data.next(); + return next; + } + + + public void remove() { + throw new UnsupportedOperationException( + "This iterator does not support remove operation."); + } + } + + @Override + public List<Permission> getRequestPermission(String topiaId, int actions) { + throw new UnsupportedOperationException(); + } + + @Override + public TopiaContextImplementor getContext() { + throw new UnsupportedOperationException(); + } + + @Override + public TopiaContext getTopiaContext() { + throw new UnsupportedOperationException(); + } + +} //TopiaDAOImpl Added: trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/HqlAndParametersBuilder.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/HqlAndParametersBuilder.java (rev 0) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/HqlAndParametersBuilder.java 2013-10-01 13:15:11 UTC (rev 2807) @@ -0,0 +1,134 @@ +package org.nuiton.topia.persistence; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.Arrays; +import java.util.Map; +import java.util.Set; + +/** + * A builder to create syntactically correct hql and associated parameters + * given properties or after various constraint adds. + * + * It may be used in a dao to ease dynamic construction of queries. + * + * @since 3.0 + * @param <E> + */ +public class HqlAndParametersBuilder<E extends TopiaEntity> { + + protected Class<E> entityClass; + + protected Set<String> whereClauses = Sets.newLinkedHashSet(); + + protected Map<String, Object> parameters = Maps.newLinkedHashMap(); + + protected Set<String> orderByArguments; + + public HqlAndParametersBuilder(Class<E> entityClass) { + this.entityClass = entityClass; + } + + public Set<String> getWhereClauses() { + return whereClauses; + } + + public void setWhereClauses(Set<String> whereClauses) { + this.whereClauses = whereClauses; + } + + public void addNull(String property) { + whereClauses.add(property + " is null"); + } + + public void setParameters(Map<String, Object> parameters) { + this.parameters = parameters; + } + + public void setOrderByArguments(Set<String> orderByArguments) { + this.orderByArguments = orderByArguments; + } + + public void setOrderByArguments(String... orderByArguments) { + Set<String> orderByArgumentsAsSet = Sets.newLinkedHashSet(); + orderByArgumentsAsSet.addAll(Arrays.asList(orderByArguments)); + this.orderByArguments = orderByArgumentsAsSet; + } + + public void addEquals(String property, Object value) { + if (value == null) { + addNull(property); + } else { + String hqlParameterName = findAvailableHqlParameterName(property); + whereClauses.add(property + " = :" + hqlParameterName); + parameters.put(hqlParameterName, value); + } + } + + public void addIn(String property, Iterable<Object> values) { + Preconditions.checkArgument(!Iterables.isEmpty(values)); + if (Iterables.size(values) == 1) { + addEquals(property, Iterables.getOnlyElement(values)); + } else { + boolean propertyMayBeNull = false; + Set<String> hqlParameterNames = Sets.newLinkedHashSet(); + for (Object value : values) { + if (value == null) { + propertyMayBeNull = true; + } else { + String hqlParameterName = findAvailableHqlParameterName(property); + parameters.put(hqlParameterName, value); + } + } + String inClause = property + " in (" + StringUtils.join(hqlParameterNames, ", ")+ ")"; + String whereClause = inClause; + if (propertyMayBeNull) { + whereClause = property + " is null or " + inClause; + } + whereClauses.add(whereClause); + } + } + + public void addContains(String property, Object value) { + String hqlParameterName = findAvailableHqlParameterName(property); + whereClauses.add(":" + hqlParameterName + " in elements(" + property + ")"); + parameters.put(hqlParameterName, value); + } + + public String getHql() { + StringBuilder hqlStringBuilder = new StringBuilder(); + hqlStringBuilder.append("from ").append(entityClass.getCanonicalName()); + if ( ! whereClauses.isEmpty()) { + hqlStringBuilder.append(" where ").append(StringUtils.join(whereClauses, " and ")); + } + if (CollectionUtils.isNotEmpty(orderByArguments)) { + hqlStringBuilder.append(" order by ").append(StringUtils.join(orderByArguments, ", ")); + } + String hql = hqlStringBuilder.toString(); + return hql; + } + + protected String findAvailableHqlParameterName(String propertyName) { + String parameterName = propertyName; + int suffix = 0; + while (parameters.containsKey(parameterName)) { + suffix += 1; + parameterName = propertyName + suffix; + } + return parameterName; + } + + public Map<String, Object> getHqlParameters() { + return parameters; + } + + public boolean isOrderByClausePresent() { + return CollectionUtils.isNotEmpty(orderByArguments); + } + +} Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaDAO.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaDAO.java 2013-09-27 18:43:30 UTC (rev 2806) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaDAO.java 2013-10-01 13:15:11 UTC (rev 2807) @@ -701,7 +701,9 @@ * @param alias optional alias to use in query * @return the hql query * @since 2.6.14 + * @deprecated no longer accessible from outside DAO */ + @Deprecated String createSimpleQuery(String alias); //------------------------------------------------------------------------// Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaDAOImpl.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaDAOImpl.java 2013-09-27 18:43:30 UTC (rev 2806) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaDAOImpl.java 2013-10-01 13:15:11 UTC (rev 2807) @@ -341,7 +341,7 @@ if (entity instanceof TopiaEntityContextable) { TopiaEntityContextable contextable = (TopiaEntityContextable)entity; - contextable.setTopiaContext(getContext()); + // contextable.setTopiaContext(getContext()); } // save entity Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaEntityAbstract.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaEntityAbstract.java 2013-09-27 18:43:30 UTC (rev 2806) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaEntityAbstract.java 2013-10-01 13:15:11 UTC (rev 2807) @@ -25,6 +25,9 @@ package org.nuiton.topia.persistence; +import org.nuiton.topia.TopiaException; +import org.nuiton.topia.framework.TopiaFiresSupport; + import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.beans.VetoableChangeListener; @@ -32,11 +35,6 @@ import java.util.Date; import java.util.List; -import org.nuiton.topia.TopiaContext; -import org.nuiton.topia.TopiaException; -import org.nuiton.topia.framework.TopiaContextImplementor; -import org.nuiton.topia.framework.TopiaFiresSupport; - /** * Classe de base de toutes les entités, cela permet de concentrer le code * technique dans cette classe. L'identifiant peut-etre n'importe quoi Aucune @@ -210,11 +208,8 @@ if (fireSupport == null) { if (this instanceof TopiaEntityContextable) { TopiaEntityContextable contextable = (TopiaEntityContextable) this; - TopiaContext context = contextable.getTopiaContext(); - if (context instanceof TopiaContextImplementor) { - TopiaContextImplementor contextImpl = (TopiaContextImplementor) context; - fireSupport = contextImpl.getFiresSupport(); - } + AbstractTopiaDAO topiaDAO = contextable.getTopiaDAO(); + fireSupport = topiaDAO.getTopiaFiresSupport(); } } return fireSupport; Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaEntityContextable.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaEntityContextable.java 2013-09-27 18:43:30 UTC (rev 2806) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaEntityContextable.java 2013-10-01 13:15:11 UTC (rev 2807) @@ -26,7 +26,6 @@ package org.nuiton.topia.persistence; import org.nuiton.topia.TopiaContext; -import org.nuiton.topia.TopiaException; /** * {@link TopiaEntity} with {@link TopiaContext} support (injected by @@ -40,28 +39,7 @@ */ public interface TopiaEntityContextable extends TopiaEntity { - String PROPERTY_TOPIA_CONTEXT = "topiaContext"; - - /** @deprecated since 3.0, will be removed in 3.1, use {@link TopiaEntityContextable#PROPERTY_TOPIA_CONTEXT} instead */ - @Deprecated - String TOPIA_CONTEXT = PROPERTY_TOPIA_CONTEXT; - /** - * Set topia context. - * - * @param topiaContext topia context - * @throws TopiaException if current topia entity context is not null - */ - void setTopiaContext(TopiaContext topiaContext) throws TopiaException; - - /** - * Get topia context. - * - * @return topia context - */ - TopiaContext getTopiaContext(); - - /** * Update entity in persistence context. */ void update(); @@ -71,4 +49,8 @@ */ void delete(); + void setTopiaDAO(AbstractTopiaDAO topiaDAO); + + AbstractTopiaDAO getTopiaDAO(); + }
participants (1)
-
bleny@users.nuiton.org