r2742 - in trunk/topia-persistence: . src/main/java/org/nuiton/topia src/main/java/org/nuiton/topia/framework src/main/java/org/nuiton/topia/generator src/main/java/org/nuiton/topia/persistence src/site/rst/user src/test/java/org/nuiton/topia/framework src/test/java/org/nuiton/topia/generator src/test/java/org/nuiton/topia/test
Author: echatellier Date: 2013-07-05 18:04:49 +0200 (Fri, 05 Jul 2013) New Revision: 2742 Url: http://nuiton.org/projects/topia/repository/revisions/2742 Log: refs #2736 : Remove topia query Removed: trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaQuery.java trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/QueryHelperTransformer.java trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaDAODeprecated.java trunk/topia-persistence/src/site/rst/user/TopiaQuery.rst trunk/topia-persistence/src/test/java/org/nuiton/topia/framework/TopiaQueryTest.java trunk/topia-persistence/src/test/java/org/nuiton/topia/generator/QueryHelperTransformerTest.java trunk/topia-persistence/src/test/java/org/nuiton/topia/test/ano1991/ Modified: trunk/topia-persistence/pom.xml trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaContext.java trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaContextImpl.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 Modified: trunk/topia-persistence/pom.xml =================================================================== --- trunk/topia-persistence/pom.xml 2013-07-05 15:29:40 UTC (rev 2741) +++ trunk/topia-persistence/pom.xml 2013-07-05 16:04:49 UTC (rev 2742) @@ -244,8 +244,7 @@ org.nuiton.eugene.java.JavaInterfaceTransformer, org.nuiton.eugene.java.JavaBeanTransformer, org.nuiton.topia.generator.EntityDTOTransformer, - org.nuiton.topia.generator.BinderHelperTransformer, - org.nuiton.topia.generator.QueryHelperTransformer + org.nuiton.topia.generator.BinderHelperTransformer </templates> <fullPackagePath>org.nuiton.topia</fullPackagePath> <defaultPackage>org.nuiton.topia</defaultPackage> Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaContext.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaContext.java 2013-07-05 15:29:40 UTC (rev 2741) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaContext.java 2013-07-05 16:04:49 UTC (rev 2742) @@ -31,7 +31,6 @@ import org.nuiton.topia.event.TopiaEntityVetoable; import org.nuiton.topia.event.TopiaTransactionListener; import org.nuiton.topia.event.TopiaTransactionVetoable; -import org.nuiton.topia.framework.TopiaQuery; import org.nuiton.topia.framework.TopiaService; import org.nuiton.topia.persistence.TopiaEntity; @@ -175,31 +174,6 @@ TopiaEntity findByTopiaId(String topiaId) throws TopiaException; /** - * Retrieve results executing a simple {@code query}. Generally this method - * is used for complex query where output type is specific (more than one - * element in the SELECT). - * - * @param query TopiaQuery to execute - * @return a List of results as hibernate give us - * @throws TopiaException - * @deprecated since 2.6.12, {@link TopiaQuery} will be removed in version 3.0 - */ - @Deprecated - List findByQuery(TopiaQuery query) throws TopiaException; - - /** - * Instantiate a new TopiaQuery. - * - * @param entityClass main entity class for the Query - * @param alias alias of the entity in the Query - * @return a new TopiaQuery - * @see TopiaQuery - * @deprecated since 2.6.12, {@link TopiaQuery} will be removed in version 3.0 - */ - @Deprecated - TopiaQuery createQuery(Class<?> entityClass, String alias); - - /** * Permet de faire une requete HQL hibernate directement sur la base. * * @param hql la requete a faire Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaContextImpl.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaContextImpl.java 2013-07-05 15:29:40 UTC (rev 2741) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaContextImpl.java 2013-07-05 16:04:49 UTC (rev 2742) @@ -887,17 +887,6 @@ } @Override - public List<?> findByQuery(TopiaQuery query) throws TopiaException { - return query.execute(this); - } - - @SuppressWarnings({"unchecked"}) - @Override - public TopiaQuery createQuery(Class<?> entityClass, String alias) { - return new TopiaQuery((Class<? extends TopiaEntity>)entityClass, alias); - } - - @Override public List<?> findAll(String hql, Object... args) throws TopiaException { checkClosed(_("topia.persistence.error.unsupported.operation.on.closed.context", "findAll")); Deleted: trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaQuery.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaQuery.java 2013-07-05 15:29:40 UTC (rev 2741) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaQuery.java 2013-07-05 16:04:49 UTC (rev 2742) @@ -1,1802 +0,0 @@ -/* - * #%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% - */ - -package org.nuiton.topia.framework; - -import org.apache.commons.beanutils.PropertyUtils; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.ObjectUtils; -import org.apache.commons.lang3.RandomStringUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.topia.TopiaContext; -import org.nuiton.topia.TopiaException; -import org.nuiton.topia.persistence.TopiaEntity; -import org.nuiton.util.StringUtil; - -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -/** - * Query HQL managment to simplify usage of {@link TopiaContext#findAll(String, - * Object...) }. - * <p/> - * TODO-FD20091224 JUnit Tests - * <p/> - * <pre> - * This class is used to construct a HQL query and then execute it from a - * TopiaContext. The TopiaQuery is linked to a TopiaEntity which - * is the main element manipulated in the query. There is two parts in using - * this class : - * - construction of the query, using add, addFrom, addOrder, addSelect, - * addGroup, ... - * - execution of the query, using executeToEntityList, executeToEntity, - * executeToInteger, ... - * - * Construction - * ============ - * - * This class make easier the way to construct a HQL query. - * - * Example 1 : - * ----------- - * - * SQL : - * "SELECT * FROM PersonImpl WHERE firstName LIKE 'M%' AND year > 1980" - * - * HQL using {@link TopiaContext#findAll(String, Object...) } : - * TopiaContext context = rootContext.beginTransaction(); - * context.find("FROM " + Person.class.getName() + " WHERE firstName LIKE - * :firstName AND year > :year", - * "firstName", "M%", year, 1980); - * - * TopiaQuery : - * TopiaQuery query = TopiaQuery.createQuery(Person.class).add( - * Person.FIRST_NAME, Op.LIKE, "M%").add(Person.YEAR, Op.GT, 1980); - * - * But the real advantage is when you have some parameters to test before - * adding - * them to the query. With the older method, it was tidious to construct - * and add parameters to finally use the find method from TopiaContext. - * - * Example 2 : - * ----------- - * - * HQL using {@link TopiaContext#findAll(String, Object...) } : - * TopiaContext context = rootContext.beginTransaction(); - * - * String query = "FROM " + Person.class.getName(); - * List<Object> params = new ArrayList<Object>(); - * String separator = " WHERE "; - * // company parameter can be null - * if (company != null) { - * query += separator + "company = :company"; - * params.add("company"); - * params.add(company); - * separator = " AND "; - * } - * - * // contact paramater can be null - * if (contact != null) { - * query += separator + "contact = :contact"; - * params.add("contact"); - * params.add(contact); - * separator = " AND "; - * } - * - * context.findAll(query, params.toArray()); - * - * Here we have only two non obligatory params, but imagine if we must have - * almost 6 or 7 parameters like this ! - * - * TopiaQuery : - * TopiaQuery query = TopiaQuery.createQuery(Person.class); - * - * if (company != null) { - * query.add(Person.COMPANY, company); - * } - * - * if (contact != null) { - * query.add(Person.CONTACT, contact); - * } - * - * Many ways to create the same query : - * ------------------------------------ - * - * You can use multiple different manners to create a query, it depends on the - * complexicity. More complex is the query, more easier is to construct it. - * - * HQL : "FROM PersonImpl AS P WHERE (P.company IS NULL OR P.company = - * :company) - * AND P.firstName LIKE :firstName" - * - * Using TopiaQuery and an Alias (these different queries are equivalent) : - * query = TopiaQuery.createQuery(Person.class, "P"); - * 1- query.add("(P.company IS NULL OR P.company = :company") AND P.firstName - * LIKE :firstName") - * .addParam("company", company).addParam("firstName",firstName + "%"); - * 2- query.add("P.company IS NULL OR P.company = :company") - * .add("P.firstName LIKE :firstName").addParam("company", company) - * .addParam("firstName",firstName + "%"); - * 3- query.add("P.company IS NULL OR P.company = :company") - * .add("P.firstName", Op.LIKE, firstName + "%") - * .addParam("company", company); - * 4- query.addNullOr("P.company", Op.EQ, company). - * add("P.firstName", Op.LIKE, firstName + "%"); - * - * You can use TopiaQuery to create a subquery in an other TopiaQuery, you have - * to use the method {@link #fullQuery() } to get the full query in HQL and - * give - * it as a string in the other TopiaQuery. - * - * Execution - * ========= - * - * After construction, you can execute the query in different ways. - * - * Default method : - * ---------------- - * - * - execute : as the same result as - * {@link TopiaContext#findAll(String, Object...) } - * - * Depends on entity type ; - * ------------------------ - * - * - executeToEntity : only one result, the first one - * - executeToEntityList : all results returned in a List - * - executeToEntityMap : all results returned in a Map with key defined by - * user - * or topiaId by default - * - * For aggregate : - * --------------- - * - * These methods have in argument the SELECT to execute the query. The previous - * SELECT (if defined) will not be deleted, but temporarly not used. - * - * - executeToInteger : for example for "SUM", "COUNT" - * - executeToString : for example for "MAX" - * - executeCount : directly a "count(*)" - * - executeToObject : for other type of possible result (Long, Boolean, - * Double, - * ...) - * - * Property loading - * ================ - * - * When using Hibernate, some times, Entities linked to the main one will be - * lazy initialized, but you want them directly when the query will be executed - * to avoid problems when closing context. You can use the method - * {@link #addLoad(String...) } to tell the TopiaQuery to load some - * properties when executing the query. After that, you don't need to call them - * for loading them in Hibernate. - * - * The syntax is the same as a property in HQL query using delegation : - * "person.company" where person and company are entities. - * - * Note : loading only available on collection or entities but not property - * on a collection of entities which must be made manually. - * - * For a Contact which is linked to a person (entity) and the person linked to - * company (entity) you can add to a TopiaQuery<Contact> : - * query.addLoad("person.company") - * - * For a list of addresses (entity) in the contact you can do : - * query.addLoad("addresses") - * - * But it's not possible to do for example with meeting (entity) linked to the - * contact and responsible (entity) linked to a meeting : - * query.addLoad("meetings.responsible") - * - * </pre> - * <p/> - * Created: 21 déc. 2009 - * - * @author fdesbois - * @version $Revision$ - * @since 2.3.0 - * @deprecated since 2.6.12, {@link TopiaQuery} will be removed in version 3.0 - */ -@Deprecated -public class TopiaQuery { - - private static final Log log = LogFactory.getLog(TopiaQuery.class); - - public static final String FROM_SEPARATOR_DEFAULT = ","; - - public static final String FROM_SEPARATOR_JOIN = "JOIN"; - - public static final String FROM_SEPARATOR_LEFT_JOIN = "LEFT JOIN"; - - /** Params for HQL query. */ - protected List<Object> params; - -// /** Select part of the query * */ -// protected StringBuilder select; - - /** - * To keep SELECT part of the query filled by user. - * - * @since 2.6.7 - */ - protected List<String> userSelects; - - /** - * To keep GROUP BY part of the query filled by user. - * - * @since 2.6.7 - */ - protected List<String> groupBys; - - /** - * To keep ORDER BY part of the query filled by user. - * - * @since 2.6.7 - */ - protected List<String> orderBys; - - /** - * To keep WHERE part of the query filled by user. - * - * @since 2.6.7 - */ - protected List<String> wheres; - - protected boolean distinct; - - //TODO tchemit-2012-02-01 Remove this (see Evol #1931) - - /** From part of the query. */ - protected StringBuilder from; - - //TODO tchemit-2012-02-01 Remove this (see Evol #1931) -// /** Where part of the query. */ -// protected StringBuilder where; - -// /** Order By part of the query. */ -// protected StringBuilder orderBy; - -// /** Group By part of the query. */ -// protected StringBuilder groupBy; - - protected Integer startIndex; - - protected Integer endIndex; - -// /** Used to determine if parentheses are needed for Where statement. */ -// protected boolean parentheses; - - protected List<String> propertiesToLoad; - - protected String mainAlias; - - /** Enum to simmplify using operation in query. */ - public enum Op { - - /** EQUALS. */ - EQ("="), - /** GREATER THAN. */ - GT(">"), - /** GREATER OR EQUALS. */ - GE(">="), - /** LIKE for String manipulation. */ - LIKE("LIKE"), - /** LESS THAN. */ - LT("<"), - /** LESS OR EQUALS. */ - LE("<="), - /** IS NOT NULL. */ - NOT_NULL("IS NOT NULL"), - /** IS NULL. */ - NULL("IS NULL"), - /** NOT EQUAL. */ - NEQ("!="), - /** IN. */ - IN("IN"), - /** NOT IN. */ - NOT_IN("NOT IN"); - - protected String value; - - /** - * Constructor of the Op Enum. - * - * @param value corresponding to the String for the query - */ - Op(String value) { - this.value = value; - } - - @Override - public String toString() { - return value; - } - } - - public TopiaQuery() { -// parentheses = true; - } - - /** - * Create a TopiaQuery based on the {@code entityClass}. The from statement - * is automatically set. - * - * @param mainEntityClass used as from part of the query - */ - public TopiaQuery(Class<? extends TopiaEntity> mainEntityClass) { - this(); - setFrom(mainEntityClass); - } - - /** - * Create a TopiaQuery based on the {@code entityClass}. The from statement - * is automatically set, the select statement must be necessary in some - * case, the query will manage this case using the mainAlias by default. - * - * @param mainEntityClass used as from part of the query - * @param alias for the mainEntityClass - */ - public TopiaQuery(Class<? extends TopiaEntity> mainEntityClass, - String alias) { - this(); - setFrom(mainEntityClass, alias); - } - - /** - * Set the mainEntity in the from part of the query. - * - * @param mainEntityClass type of the mainEntity - * @return the TopiaQuery - */ - public TopiaQuery setFrom(Class<? extends TopiaEntity> mainEntityClass) { - setFrom(mainEntityClass, null); - return this; - } - - /** - * Set the mainEntity in the from part of the query and use an alias for - * this mainEntity. - * - * @param mainEntityClass type of the mainEntity - * @param alias for the entity in the query - * @return the TopiaQuery - */ - public TopiaQuery setFrom(Class<? extends TopiaEntity> mainEntityClass, - String alias) { - from = new StringBuilder(" FROM ").append(mainEntityClass.getName()); - mainAlias = alias; - if (StringUtils.isNotEmpty(mainAlias)) { - from.append(' ').append(alias); - } - return this; - } - - /** - * Add an element to the from in the query. Used to add some other data in - * the query. The default separator used is the ", ". - * - * @param str the element to add - * @return the TopiaQuery - * @see #addFrom(Class, String) - * @see #addJoin(String, String, boolean) - * @see #addLeftJoin(String, String, boolean) - * @deprecated since 2.3.4 use correct addFrom or addJoin or addLeftJoin - */ - @Deprecated - public TopiaQuery addFrom(String str) { - return addFrom(FROM_SEPARATOR_DEFAULT, str, null); - } - - /** - * Add an element to the from in the query. Used to add some other data in - * the query or for join as specific {@code separator}. - * - * @param property the property to add - * @param alias alias of the property to add in form part of the query - * @param separator The separator to use before adding the element (if null - * the {@link #FROM_SEPARATOR_DEFAULT} will be used). - * @return the TopiaQuery - * @since 2.3.4 - */ - protected TopiaQuery addFrom(String separator, String property, String alias) { - if (!separator.equals(FROM_SEPARATOR_DEFAULT)) { - from.append(' '); - } - from.append(separator).append(' ').append(property); - - if (alias != null) { - from.append(' ').append(alias); - } - return this; - } - - /** - * Add a inner join {@code property} to the query with {@code alias}. - * The join is done in From statement as : FROM Contact C JOIN C.boat B. The - * added part is 'JOIN C.boat B' using addJoin("C.boat", "B", false). The order - * of calling {@link #addFrom(Class, String)} or this method is very important. - * The first element in the FROM is always the main entity of the query. - * - * @param property Property name to use as a Join - * @param alias Alias of the property in the query - * @param fetch Add FETCH keyword to load the property in result (avoid - * lazy initialization) - * @return the TopiaQuery - * @since 2.3.4 - */ - public TopiaQuery addJoin(String property, String alias, boolean fetch) { - return addFromJoin(FROM_SEPARATOR_JOIN, property, alias, fetch); - } - - - /** - * Add a left join {@code property} to the query with {@code alias}. - * The join is done in From statement as : FROM Contact C LEFT JOIN C.boat B. - * The added part is 'LEFT JOIN C.boat B' using addJoin("C.boat", "B", false). - * The order of calling {@link #addFrom(Class, String)} or this method is - * very important. The first element in the FROM is always the main entity - * of the query. - * - * @param property Property name to use as a Join - * @param alias Alias of the property in the query - * @param fetch Add FETCH keyword to load the property in result (avoid - * lazy initialization) - * @return the TopiaQuery - * @since 2.3.4 - */ - public TopiaQuery addLeftJoin(String property, String alias, boolean fetch) { - return addFromJoin(FROM_SEPARATOR_LEFT_JOIN, property, alias, fetch); - } - - protected TopiaQuery addFromJoin(String separator, String property, - String alias, boolean fetch) { - String sep = separator; - if (fetch) { - sep = new StringBuilder(separator).append(" FETCH").toString(); - } - return addFrom(sep, property, alias); - } - - /** - * Add an other entity type to the from in the query. - * - * @param entityClass different from the mainEntity - * @return the TopiaQuery - */ - public TopiaQuery addFrom(Class<? extends TopiaEntity> entityClass) { - return addFrom(entityClass, null); - } - - /** - * Add an other entity type to the from in the query with an alias. - * - * @param entityClass different from the mainEntity - * @param alias of the entity in the query - * @return the TopiaQuery - */ - public TopiaQuery addFrom(Class<? extends TopiaEntity> entityClass, - String alias) { - return addFrom(FROM_SEPARATOR_DEFAULT, entityClass.getName(), alias); - } - - /** - * Get the full query. - * - * @return a String corresponding to the full query. - */ - public String fullQuery() { - StringBuilder result = new StringBuilder(); - StringBuilder selectStatement = new StringBuilder("SELECT "); - if (distinct) { - selectStatement.append("DISTINCT "); - } - if (CollectionUtils.isNotEmpty(userSelects)) { - - result.append(selectStatement); - result.append(StringUtils.join(userSelects, ',')); - } else if (StringUtils.contains(from.toString(), ',') && - StringUtils.isNotEmpty(mainAlias)) { - // Set default select if there is more than one table in from - // part and main alias is defined - // Note : maybe a problem with using new {@link #addFrom(String, String) with other than ',' separator - result.append(selectStatement).append(mainAlias); - } - -// if (select != null) { -// result.append(selectStatement).append(select); -// // Set default select if there is more than one table in from -// // part and main alias is defined -// // Note : maybe a problem with using new {@link #addFrom(String, String) with other than ',' separator -// } else if (StringUtils.contains(from.toString(), ',') && -// StringUtils.isNotEmpty(mainAlias)) { -// result.append(selectStatement).append(mainAlias); -// } - result.append(from); - - if (CollectionUtils.isNotEmpty(wheres)) { - result.append(" WHERE "); - boolean first = true; - boolean moreThanOne = wheres.size() > 1; - for (String where : wheres) { - if (!first) { - result.append(" AND "); - } - if (moreThanOne) { - result.append('('); - } - result.append(where); - if (moreThanOne) { - result.append(')'); - } - first = false; - } - } - if (CollectionUtils.isNotEmpty(groupBys)) { - result.append(" GROUP BY ").append(StringUtils.join(groupBys, ',')); - } - if (CollectionUtils.isNotEmpty(orderBys)) { - result.append(" ORDER BY ").append(StringUtils.join(orderBys, ',')); - } -// if (where != null) { -// result.append(where); -// } -// if (groupBy != null) { -// result.append(groupBy); -// } -// if (orderBy != null) { -// result.append(orderBy); -// } - return StringUtils.trim(result.toString()); - } - - /** - * Add a HQL parameter to the Query. - * - * @param id identification of the param in the query - * @param paramValue value of the param - * @return the TopiaQuery - */ - public TopiaQuery addParam(String id, Object paramValue) { - getParams().add(id); - getParams().add(paramValue); - return this; - } - - /** - * Add muliple paramaters to the Query. The key of each param will be tested - * if not already exist in the existing params list and will be renamed in - * this case. - * - * @param params a list of HQL params with key and value in order. - * @return the TopiaQuery - * @see TopiaQuery#getValueName(String) - */ - public TopiaQuery addParams(List<Object> params) { - for (int i = 0; i < params.size(); i += 2) { - String paramName = (String) params.get(i); - addParam(getValueName(paramName), params.get(i + 1)); - } - return this; - } - - public List<Object> getParams() { - if (params == null) { - params = new ArrayList<Object>(); - } - return params; - } - - /** - * Return the mainAlias set from constructor. - * - * @return a String or null if no alias is set - */ - public String getMainAlias() { - return mainAlias; - } - - /** - * Add a property to load when query is executed. Used to avoid - * LazyInitializationException for property needed after closing context. - * The property is a string like those in HQL query. - * <pre> - * Exemples : - * - "person.company" (Property TopiaEntity person linked to the result - * entity in query and company linked to person) - * --> calling myEntity.getPerson().getCompany(); - * - "partyRoles" (Property Collection partyRoles linked to the result - * entity in query) - * --> calling myEntity.getPartyRoles().size(); - * </pre> - * - * @param properties List of properties to load - * @return the TopiaQuery - */ - public TopiaQuery addLoad(String... properties) { - getPropertiesToLoad().addAll(Arrays.asList(properties)); - return this; - } - - /** - * Used to load properties during query execution using FETCH keyword. This - * keyword is used in a JOIN, so the alias is needed to identify properties - * to load. - * </p> - * Also an empty SELECT statement will be defined to retrieve the correct - * entity depends on the mainEntity type in the query. Carefull using - * addFetch, hibernate doesn't support more than 3 or 4 join. In this case, - * you can use {@link #addLoad(String...)} or load manually the entities - * wanted. - * - * @param properties Properties to load during query execution - * @return the TopiaQuery - */ - public TopiaQuery addFetch(String... properties) { - - // Note : creating alias is not very efficient if other parameters is needed - // Maybe the solution is to throw an exception if no mainAlias is defined - - // Check mainAlias, necessary to use join fetch - boolean needAlias = false; - if (StringUtils.isEmpty(mainAlias)) { - mainAlias = RandomStringUtils.randomAlphabetic(4); - from.append(' ').append(mainAlias); - needAlias = true; - } - - // Init select for single result -// if (select == null) { -// setSelect(mainAlias); -// } - if (userSelects == null) { - setSelect(mainAlias); - } - - for (String current : properties) { - // Add missing alias if needed - String property = needAlias ? - getProperty(mainAlias, current) : current; - - // Split property on . - String[] parts = property.split("\\."); - - // First alias need to be a property in query - String alias = parts[0]; - - for (int i = 1; i < parts.length; i++) { - // Construct property with current alias - String propertyToJoin = getProperty(alias, parts[i]); - - // If next occurence exists create a new alias - if ((i + 1) < parts.length) { - alias = RandomStringUtils.randomAlphabetic(4); - } else { - // loop will stop, last alias is null - alias = null; - } - - // Add the property in left join with fetch to true - addLeftJoin(propertyToJoin, alias, true); - } - } - return this; - } - - protected List<String> getPropertiesToLoad() { - if (propertiesToLoad == null) { - propertiesToLoad = new ArrayList<String>(); - } - return propertiesToLoad; - } - - /** - * @param where Where statement to add - * @return TopiaQuery - * @deprecated since 2.3.4, use {@link #addWhere(String)} instead - */ - @Deprecated - public TopiaQuery add(String where) { - return addWhere(where); - } - - /** - * Add a where element to the Query. Could be anything. Parentheses are - * added automatically (even if there are not needed). - * - * @param where element to add - * @return the TopiaQuery - * @since 2.3.4 - */ - public TopiaQuery addWhere(String where) { - if (StringUtils.isNotEmpty(where)) { - if (wheres == null) { - wheres = new ArrayList<String>(); - } - wheres.add(where); -// // Reinitialize parentheses boolean for next add call -// parentheses = true; - } -// if (this.where == null) { -// this.where = new StringBuilder(" WHERE "); -// } else { -// this.where.append(" AND "); -// } -// if (parentheses) { -// this.where.append('('); -// } -// this.where.append(where); -// if (parentheses) { -// this.where.append(')'); -// } -// // Reinitialize parentheses boolean for next add call -// parentheses = true; - return this; - } - - /** - * @param paramName name of the parameter to add - * @param constraint constraint to use - * @param paramValue value of this parameter - * @return TopiaQuery - * @deprecated since 2.3.4, use {@link #addWhere(String, Op, Object)} instead - */ - @Deprecated - public TopiaQuery add(String paramName, Op constraint, Object paramValue) { - return addWhere(paramName, constraint, paramValue); - } - - /** - * Add an element to the query. The parameter will be automatically added. - * The {@code operator} is needed to determine what type of operation it is. - * Ex : add("boat", Op.EQ, boat) means -> boat = :boat. Also if the paramValue - * is Null, the paramName will be added to the query with the constraint - * null (IS NULL). - * <p/> - * TODO-fdesbois-2010-05-26 : maybe manage more than one paramValue with Object... Depends on operator - * - * @param paramName the name of the parameter in the query (attribute of - * the entity) - * @param operator the operation concerned - * @param paramValue the value of the parameter (an other entity, a String, - * ...) - * @return the TopiaQuery - * @since 2.3.4 - */ - public TopiaQuery addWhere(String paramName, Op operator, Object paramValue) { - StringBuilder result = new StringBuilder(paramName).append(' '); - if (log.isTraceEnabled()) { - log.trace("paramValue = " + paramValue); - } - if (paramValue == null) { - result.append(Op.NULL); - } else { - String valueName = getValueName(paramName); - if (Op.IN == operator || Op.NOT_IN == operator) { - - result.append(operator).append(" (:").append(valueName).append(')'); - } else { - result.append(operator).append(" :").append(valueName); - } - addParam(valueName, paramValue); - } -// parentheses = false; - return addWhere(result.toString()); - - } - - protected String getValueName(String paramName) { - int dot = paramName.lastIndexOf('.'); - String valueName = paramName; - if (dot != -1) { - valueName = paramName.substring(dot + 1); - } - - // If the paramName contains a function, escape parenthesis - valueName = valueName.replace('(', '_'); - valueName = valueName.replace(')', '_'); - - if (getParams().contains(valueName)) { - valueName = valueName + "_" + - RandomStringUtils.randomAlphanumeric(4); - } - return valueName; - } - - /** - * @param paramName name of the parameter to add - * @param paramValue value of this parameter - * @return TopiaQuery - * @since 2.3.1 - * @deprecated since 2.3.4, use {@link #addEquals(String, Object...)} instead - */ - @Deprecated - public TopiaQuery add(String paramName, Object... paramValue) { - return addEquals(paramName, paramValue); - } - - /** - * Add an element to the query. The parameter will be automatically added. - * The default constrainst operation is Op.EQ for EQUALS. Ex : add("boat", - * boat) means -> boat = :boat. If you add more than one values, the - * statement IN will be used. You can also have a null value in the {@code - * paramValue} list (except if it's the only one value, it's ambiguous). - * Note : this method do nothing if the {@code paramValue} is not defined. - * You can also set {@code paramValue} to null if you want the {@code - * paramName} to be null in the query. - * - * @param paramName name of the parameter in the query - * @param paramValue values of the parameter - * @return the TopiaQuery - * @see TopiaQuery#addWhere(String, Op, Object) - * @since 2.3.4 - */ - public TopiaQuery addEquals(String paramName, Object... paramValue) { - if (paramValue == null) { - return addWhere(paramName, Op.EQ, null); - } - int length = paramValue.length; - // Do nothing if there is no value defined - if (length == 0) { - return this; - } - // Only one paramValue - if (length == 1) { - if (log.isTraceEnabled()) { - log.trace("Only one value " + Arrays.toString(paramValue)); - } - return addWhere(paramName, Op.EQ, paramValue[0]); - } - // Multiple values is defined - StringBuilder values = new StringBuilder(); - int count = 1; - // Used if one of the value is null - boolean addNull = false; - for (Object value : paramValue) { - if (value != null) { - // Add the valueName to the values list for IN statement - String valueName = getValueName(paramName + count); - if (count != 1) { - values.append(", "); - } - values.append(':').append(valueName); - addParam(valueName, value); - count++; - } else { - addNull = true; - } - } - // Create buffer for IN statement with values - StringBuilder buffer = new StringBuilder(); - buffer.append(paramName).append(" IN (").append(values).append(")"); - // Add the OR statement for null value if needed - if (addNull) { - buffer.append(" OR "). - append(paramName).append(' ').append(Op.NULL.toString()); - } else { -// // no parentheses needed in this case (no OR statement) -// parentheses = false; - } - return addWhere(buffer.toString()); - } - - /** - * @param properties map of the properties to add - * @return TopiaQuery - * @deprecated since 2.3.4 use {@link #addEquals(Map)} - */ - @Deprecated - public TopiaQuery add(Map<String, Object> properties) { - return addEquals(properties); - } - - /** - * Add a map of properties to the where clause of the query. Each property - * will be added to the query with Op.EQ operation, the key in the map is - * the property name, and the value is the value of the parameter in the - * query. - * - * @param properties to add to the query - * @return the TopiaQuery - * @since 2.3.4 - */ - public TopiaQuery addEquals(Map<String, Object> properties) { - for (String key : properties.keySet()) { - addEquals(key, properties.get(key)); - } - return this; - } - - /** - * Add an element to the query with the constraint Not null. - * - * @param paramName name of the parameter in the query - * @return the TopiaQuery - */ - public TopiaQuery addNotNull(String paramName) { - StringBuilder result = - new StringBuilder(paramName).append(' ').append(Op.NOT_NULL); -// parentheses = false; - addWhere(result.toString()); -// parentheses = true; - return this; - } - - /** - * Add an element to the query. The nullity is tested or a constraint is - * added for that element. Ex : addNullOr("begin", Op.GT, new Date()) means - * begin IS NULL OR begin > :begin (where :begin = new Date()). - * - * @param paramName the name of the parameter in the query (attribute of - * the entity) - * @param constraint the operation concerned by the or - * @param paramValue the value of the parameter (an other entity, a String, - * ...) - * @return the TopiaQuery - */ - public TopiaQuery addNullOr(String paramName, Op constraint, - Object paramValue) { - String valueName = getValueName(paramName); - StringBuilder result = - new StringBuilder(paramName).append(' ').append(Op.NULL). - append(" OR ").append(paramName).append(constraint). - append(" :").append(valueName); - addParam(valueName, paramValue); - return addWhere(result.toString()); - } - - /** - * Add an element to the query with the constraint null. - * - * @param paramName name of the parameter in the query - * @return the TopiaQuery - */ - public TopiaQuery addNull(String paramName) { - addWhere(paramName, Op.EQ, null); - return this; - } - - /** - * Add an element with BETWEEN operation. The {@code paramName} will be - * found between {@code value1} and {@code value2}. Useful for date - * manipulations. - * - * @param paramName The name of the parameter in the query (entity property) - * @param value1 First value - * @param value2 Second value - * @return the TopiaQuery - */ - public TopiaQuery addBetween(String paramName, Object value1, Object value2) { - - String valueName = getValueName(paramName); - String valueName1 = new StringBuilder(valueName).append('1').toString(); - String valueName2 = new StringBuilder(valueName).append('2').toString(); - - addParam(valueName1, value1); - addParam(valueName2, value2); - - StringBuilder builder = - new StringBuilder(paramName). - append(" BETWEEN "). - append(':').append(valueName1). - append(" AND "). - append(':').append(valueName2); - -// parentheses = false; - addWhere(builder.toString()); -// parentheses = true; - return this; - } - - - /** - * Add link constraint between two properties. {@code elementProperty} is in - * elements of {@code containerProperty} which is a collection with same type - * than {@code elementProperty}. (HQL : elementProperty IN elements - * (containerProperty)) - * - * @param elementProperty contains in containerProperty collection - * @param containerProperty collection which contains elementProperty - * @return the TopiaQuery - * @since 2.3.4 - */ - public TopiaQuery addInElements(String elementProperty, String containerProperty) { - StringBuilder builder = new StringBuilder(elementProperty). - append(" IN elements(").append(containerProperty).append(')'); -// parentheses = false; - addWhere(builder.toString()); -// parentheses = true; - return this; - } - - /** - * Method used to add a subquery in an existing query. The params will be - * automatically checked and copied from the subquery to the current one. - * This method is used to inject {@code subquery} in WHERE part of the - * query. The {@code queryPart} is the element in the query to bind with the - * {@code subquery}. The ? character is used to inject the subquery into the - * {@code queryPart}. Ex : - * <pre> - * // Add a SUB_ELMT = (subquery) into the query - * query.addSubQuery("SUB_ELMT = (?)", subquery, false); - * </pre> - * - * @param queryPart part of the query where subquery need to be injected - * @param subquery existing topiaQuery as subquery - * @return the TopiaQuery - * @see TopiaQuery#getValueName(String) - * @since 2.3.4 - */ - public TopiaQuery addSubQuery(String queryPart, - TopiaQuery subquery) { - - List<Object> subqueryParams = subquery.getParams(); - String subqueryString = subquery.fullQuery(); - - // If no params is still defined, use those from subquery. - if (CollectionUtils.isEmpty(params)) { - addParams(subqueryParams); - } else { - for (int i = 0; i < subqueryParams.size(); i += 2) { - - String paramName = (String) subqueryParams.get(i); - Object paramValue = subqueryParams.get(i + 1); - - // Check existence of paramName - int index = params.indexOf(paramName); - - if (index == -1) { // if not defined, param is only used - // in sub-query, so add it in the whole query - addParam(paramName, paramValue); - } else { // If already defined - - Object existingValue = params.get(index + 1); - - // Only change paramName in not equals case - if (!ObjectUtils.equals(existingValue, paramValue)) { - String newParamName = getValueName(paramName); - // Replace old paramName in subquery - subqueryString = - subqueryString.replace(":" + paramName, - ":" + newParamName); - - // Add the param to the current query - addParam(newParamName, paramValue); - } - } - } - } - - // Replace ? injection by the subquery - String result = queryPart.replace("?", subqueryString); - return addWhere(result); - } - - /** - * Add an element to the select in the query. Depends on the result wanted - * in execute methods. The main entity will be automatically added only if - * an alias is initialize from constructor. If you want only this select - * element, use {@link #setSelect(String...) } method instead. - * - * @param select element to add - * @return the TopiaQuery - */ - public TopiaQuery addSelect(String... select) { - -// if (mainAlias != null && -// CollectionUtils.isNotEmpty(userSelects) && -// userSelects.contains(mainAlias)) { -// // if select is the mainAlias, do nothing -// return this; -// } -// String str = convertStringArray(select); -// // if select is the mainAlias, do nothing -// if (mainAlias != null && str.equals(mainAlias)) { -// return this; -// } - - if (userSelects == null) { - - userSelects = new ArrayList<String>(); - - if (mainAlias != null) { - - // if mainAlias is not null, add it before adding the select in argument - userSelects.add(mainAlias); - } - } - - userSelects.addAll(Arrays.asList(select)); - -// // if select is not null, add the new element to the select -// if (this.select != null) { -// this.select.append(", "); -// // if mainAlias is not null, add it before adding the select in argument -// } else if (mainAlias != null) { -// this.select = new StringBuilder(mainAlias).append(", "); -// } else { -// this.select = new StringBuilder(); -// } -// this.select.append(convertStringArray(select)); - return this; - } - - /** - * Set the select in the query. Depends on the result wanted in execute - * methods. - * - * @param select element to set - * @return the TopiaQuery - */ - public TopiaQuery setSelect(String... select) { - userSelects = new ArrayList<String>(Arrays.asList(select)); -// this.select = new StringBuilder(convertStringArray(select)); - return this; - } - - /** - * Add the distinct key word in the query. The result will not have multiple - * same values. - * - * @return the TopiaQuery - */ - public TopiaQuery addDistinct() { - distinct = true; - return this; - } - - /** - * Add an element to the order in the query. Used to add some parameters to - * order by. - * - * @param order element to add - * @return the TopiaQuery - */ - public TopiaQuery addOrder(String... order) { - if (orderBys == null) { - orderBys = new ArrayList<String>(); - } - Collections.addAll(orderBys, order); -// if (orderBy == null) { -// orderBy = new StringBuilder(" ORDER BY "); -// } else { -// orderBy.append(", "); -// } -// orderBy.append(convertStringArray(order)); - return this; - } - - public TopiaQuery addOrderDesc(String order) { - return addOrder(order + " DESC"); - } - - /** - * Add an element to the group of the query. Used to add some paramters to - * group by. - * - * @param group element to add - * @return the TopiaQuery - */ - public TopiaQuery addGroup(String... group) { - if (groupBys == null) { - groupBys = new ArrayList<String>(); - } - Collections.addAll(groupBys, group); -// if (groupBy == null) { -// groupBy = new StringBuilder(" GROUP BY "); -// } else { -// groupBy.append(", "); -// } -// groupBy.append(convertStringArray(group)); - return this; - } - -// /** -// * Helper method for array type. Each value will be separated by a comma. -// * TODO-fdesbois-2010-05-25 : replace this algo by StringUtil.join() -// * -// * @param array of String -// * @return a String with values of the array separated by a comma -// */ -// protected String convertStringArray(String... array) { -// StringBuilder result = new StringBuilder(); -// for (String value : array) { -// result.append(", ").append(value); -// } -// String str = ""; -// if (result.length() > 0) { -// str = result.substring(2); -// } -// return str; -// } - - /** - * Limit the result of the query with startIndex and endIndex. - * - * @param start first index to get from the results - * @param end last index to get from the results - * @return the TopiaQuery - */ - public TopiaQuery setLimit(int start, int end) { - startIndex = start; - endIndex = end; - return this; - } - - /** - * Remove limits previously set - * - * @return the TopiaQuery - */ - public TopiaQuery resetLimit() { - startIndex = null; - endIndex = null; - return this; - } - - /** - * Set the max results wanted for the query. - * - * @param max the number of elements wanted - * @return the TopiaQuery - */ - public TopiaQuery setMaxResults(int max) { - return setLimit(0, max - 1); - } - - /** - * Add a {@code filter} to the query that contains limit indexes, - * orderBy condition and referenceId if needed. The referenceProperty is - * necessary to use the referenceId of the {@code filter}. The filter will - * be applied on the main entity in the query (using the mainAlias if - * necessary). - * <p/> - * Note : the default orderBy is the topiaCreateDate ordered desc (the most - * recent in first) - * - * @param filter Filter to apply on the query - * @return the TopiaQuery - * @throws IllegalArgumentException if referenceId is defined but no - * referenceProperty was set - * @see #addFilter(EntityFilter, String) - */ - public TopiaQuery addFilter(EntityFilter filter) - throws IllegalArgumentException { - return addFilter(filter, null); - } - - /** - * Add a {@code filter} to the query that contains limit indexes, - * orderBy condition and referenceId if needed. In some case it's necessary - * to specify explicitely the {@code propertyToFilter} in complex queries. - * The referenceProperty need to be specifie in {@code filter} to have a - * correspondance between the referenceId and it's property in the query. By - * default, the {@code propertyToFilter} is the mainAlias of the query. - * <p/> - * Note : the default orderBy is the topiaCreateDate ordered desc (the most - * recent in first) - * - * @param filter Filter to apply on the query - * @param propertyToFilter Explicit property to filter - * @return the TopiaQuery - * @throws IllegalArgumentException if referenceId is defined but no - * referenceProperty was set - */ - public TopiaQuery addFilter(EntityFilter filter, - String propertyToFilter) - throws IllegalArgumentException { - - if (propertyToFilter == null) { - propertyToFilter = mainAlias; - } - - Integer startIndex = filter.getStartIndex(); - Integer endIndex = filter.getEndIndex(); - String orderBy = filter.getOrderBy(); - String referenceId = filter.getReferenceId(); - String referenceProperty = filter.getReferenceProperty(); - - if (log.isDebugEnabled()) { - log.debug("Filter added to the query : " + filter); - } - - // Add limits. Only startIndex do nothing. - // startIndex + endIndex provides the limit - if (startIndex != null && endIndex != null) { - setLimit(startIndex, endIndex); - - // endIndex only provides the maxResults wanted - } else if (endIndex != null) { - setMaxResults(endIndex); - } - - // Add order to the main entity in the query, splitted by comma - if (orderBy != null) { - List<String> order = new ArrayList<String>(); - for (String elmt : orderBy.split(",")) { - String property = - TopiaQuery.getProperty(propertyToFilter, elmt.trim()); - order.add(property); - } - addOrder(order.toArray(new String[order.size()])); - - // Default order by creation date - } else { - addOrderDesc(getPropertyCreateDate(propertyToFilter)); - } - - if (filter.hasReference()) { - if (referenceProperty == null) { - throw new IllegalArgumentException("Reference property need" + - " to be defined in filter to use referenceId = " + - referenceId); - } - addEquals(getPropertyId(referenceProperty), referenceId); - } - - return this; - } - - /** - * Simple execution of the query. This method use directly the find method - * in TopiaContext interface. - * - * @param transaction the TopiaContext to use for execution - * @return a List of results - * @throws TopiaException for error on query execution - * @see TopiaContext#findAll(String, Object...) - */ - public List execute(TopiaContext transaction) throws TopiaException { - String query = fullQuery(); - if (log.isDebugEnabled()) { - log.debug(this); - } - List result; - if (startIndex != null && endIndex != null) { - result = transaction.find(query, startIndex, endIndex, - getParams().toArray()); - } else { - result = transaction.findAll(query, getParams().toArray()); - } - return result; - } - - /** - * Execute the query and get a List of entity. Some properties will be - * loaded if they are prealably set using ${@link #addLoad(String...) }. - * - * @param <E> entity type - * @param transaction the TopiaContext to use for execution - * @param entityClass used to check return type of execution results - * @return a List of TopiaEntity corresponding to the entityClass in - * argument - * @throws TopiaException for error on query execution - * @throws ClassCastException if entityClass doesn't match to results - */ - public <E extends TopiaEntity> List<E> executeToEntityList( - TopiaContext transaction, Class<E> entityClass) - throws TopiaException, ClassCastException { - List res = execute(transaction); - if (log.isTraceEnabled()) { - log.trace("Properties to load : " + getPropertiesToLoad()); - } - List<E> results = new ArrayList<E>(); - for (Object o : res) { - if (o == null) { - continue; - } - if (o instanceof Object[]) { - // If it's an array, we want only the first element wich is the - // entity wanted - // We know that the array have at least one element - o = ((Object[]) o)[0]; - } - if (!entityClass.isAssignableFrom(o.getClass())) { - throw new ClassCastException(o.getClass().getName() + - " can't be cast to " + entityClass.getName() + - " o : " + o); - } - E entity = (E) o; - // Check distinct constraint for complex query where o is firstly an - // Object[] (potentially distinct results with existing entity to add) - if (!(distinct && results.contains(entity))) { - if (!getPropertiesToLoad().isEmpty()) { - loadProperties(entity); - } - results.add(entity); - } - } - return results; - } - - /** - * Execute the query and get a Map of entity with key type in argument. Some - * properties will be loaded if they are prealably set using ${@link - * #addLoad(String...) }. - * - * @param <E> entity type - * @param <K> the type of the map key - * @param transaction the TopiaContext to use for execution - * @param entityClass needed to execute the query - * @param keyName the property name of the key in the entity - * @param keyClass the key class for the result map - * @return a Map with the key type defined and the entity in value - * @throws TopiaException for error on query execution - * @throws ClassCastException if entityClass doesn't match to results - */ - public <E extends TopiaEntity, K> Map<K, E> executeToEntityMap( - TopiaContext transaction, Class<E> entityClass, - String keyName, Class<K> keyClass) - throws TopiaException, ClassCastException { - - // Use LinkedHashMap to keep insert order from list results which - // can be ordered - Map<K, E> results = new LinkedHashMap<K, E>(); - List<E> list = executeToEntityList(transaction, entityClass); - for (E elmt : list) { - Object value = loadProperty(elmt, keyName); - if (value != null && !keyClass.isAssignableFrom(value.getClass())) { - throw new ClassCastException(value.getClass().getName() + - " can't be cast to " + keyClass.getName()); - } - results.put((K) value, elmt); - } - return results; - } - - /** - * Execute the query and get a Map of entity with topiaId in key. Some - * properties will be loaded if they are prealably set using ${@link - * #addLoad(String...) }. - * - * @param <E> entity type - * @param transaction the TopiaContext to use for execution - * @param entityClass used to check return type of execution results - * @return a Map with the key type defined and the entity in value - * @throws TopiaException for error on query execution - * @throws ClassCastException if entityClass doesn't match to results - */ - public <E extends TopiaEntity> Map<String, E> executeToEntityMap( - TopiaContext transaction, Class<E> entityClass) - throws TopiaException, ClassCastException { - return executeToEntityMap(transaction, entityClass, - TopiaEntity.PROPERTY_TOPIA_ID, String.class); - } - - /** - * Execute the query and get the first result entity. Some properties will - * be loaded if they are prealably set using ${@link #addLoad(String...) }. - * - * @param <E> entity type - * @param transaction the TopiaContext to use for execution - * @param entityClass used to check return type of execution results - * @return a TopiaEntity corresponding to the entityClass in argument - * @throws TopiaException for error on query execution - * @throws ClassCastException if entityClass doesn't match to results - */ - public <E extends TopiaEntity> E executeToEntity(TopiaContext transaction, - Class<E> entityClass) - throws TopiaException, ClassCastException { - setMaxResults(1); - List<E> results = executeToEntityList(transaction, entityClass); - resetLimit(); - return !results.isEmpty() ? results.get(0) : null; - } - - /** - * Execute the query and get an Object for result. The select is overriden - * to get only the right value for return. - * - * @param transaction the TopiaContext to use for execution - * @param select the Select overriden - * @return an Object - * @throws TopiaException for error on query execution - */ - public Object executeToObject(TopiaContext transaction, String select) - throws TopiaException { - List<String> oldValue = this.userSelects; -// StringBuilder oldValue = this.select; - if (!StringUtils.isEmpty(select)) { - setSelect(select); - } - Object result = null; - setMaxResults(1); - List results = execute(transaction); - if (!results.isEmpty()) { - result = results.get(0); - } -// this.select = oldValue; - userSelects = oldValue; - resetLimit(); - return result; - } - - /** - * Execute the query and get an Integer for result. Used only for query with - * aggration select which return a Long : COUNT, SUM ... The select is - * overriden to get only the right value for return. - * - * @param transaction the TopiaContext to use for execution - * @param select the Select overriden (ex : SUM(myParam)) - * @return an Integer - * @throws TopiaException for error on query execution - */ - public int executeToInteger(TopiaContext transaction, String select) - throws TopiaException { - Long res = (Long) executeToObject(transaction, select); - return res != null ? res.intValue() : 0; - } - - /** - * Execute the query and get a String for result. Used for query with MAX, - * ... The select is overriden to get only the right value for return. - * - * @param transaction the TopiaContext to use for execution - * @param select the Select overriden (ex : MAX(myParam)) - * @return a String - * @throws TopiaException for error on query execution - */ - public String executeToString(TopiaContext transaction, String select) - throws TopiaException { - Object res = executeToObject(transaction, select); - return res != null ? (String) res : ""; - } - - /** - * Execute a simple count on the query, i.e. the number of results get from - * the query. The order is not considered to count the elements and will be - * temporarly disabled. The distinct constraint will be manage if necessary - * : - * <pre> - * COUNT(DISTINCT mainAlias) - * </pre> - * - * @param transaction the TopiaContext to use for execution - * @return an int corresponding to the number of result in the query - * @throws TopiaException for error on query execution - */ - public int executeCount(TopiaContext transaction) throws TopiaException { - List<String> oldOrderBys = orderBys; - orderBys = null; -// StringBuilder oldOrder = orderBy; -// orderBy = null; - StringBuilder count = new StringBuilder("COUNT("); - // Ano #560 : manage distinct case when the alias is set (otherwise - // no need the distinct keyword because the entity type in query is - // unique) - - //Note Ano #1930 tchemit 2012-02-01 this code does not work if a setSelect was done - -// if (distinct && StringUtils.isNotEmpty(mainAlias) && -// isUserSelectEqualsMainAlias()) { -// count.append("DISTINCT ").append(mainAlias); -// // When distinct is not set, use <pre>*</pre> -// } else { -// count.append('*'); -// } - - String mainSelect = null; - - if (distinct) { - - if (CollectionUtils.isNotEmpty(userSelects)) { - - if (userSelects.size() > 1) { - - // can not count this on multiple select... - throw new TopiaException( - "To count, can not have more than one select, but found " + - userSelects); - } - mainSelect = userSelects.get(0); - } else if (StringUtils.isNotEmpty(mainAlias)) { - - // use main alias - mainSelect = mainAlias; - } - } - - if (mainSelect != null) { - count.append("DISTINCT ").append(mainSelect); - } else { - count.append('*'); - } - count.append(')'); - int result = executeToInteger(transaction, count.toString()); - orderBys = oldOrderBys; -// orderBy = oldOrder; - return result; - } - - protected boolean isUserSelectEqualsMainAlias() { - boolean result = !CollectionUtils.isEmpty(userSelects) && - userSelects.size() == 1 && - userSelects.get(0).equals(mainAlias); - return result; - } - - /** - * Load all properties for the entity. - * - * @param entity used to load properties - * @throws TopiaException for error on query execution - */ - protected void loadProperties(TopiaEntity entity) - throws TopiaException { - for (String prop : getPropertiesToLoad()) { - if (log.isTraceEnabled()) { - log.trace("load property " + prop + " ..."); - } - List<String> str = Arrays.asList(prop.split("\\.")); - Iterator<String> it = str.iterator(); - TopiaEntity currEntity = entity; - while (it.hasNext()) { - String s = it.next(); - if (mainAlias != null && s.equals(mainAlias)) { - if (log.isTraceEnabled()) { - log.trace("Skip alias : " + mainAlias); - } - continue; - } - if (log.isTraceEnabled()) { - log.trace("Current entity : " + - currEntity.getClass().getSimpleName()); - log.trace("Current loading : " + s); - } - if (it.hasNext()) { - currEntity = loadEntityProperty(currEntity, s); - } else { - loadProperty(currEntity, s); - } - } - } - } - - /** - * Load a property of type TopiaEntity from an other entity. - * - * @param <T> type of the entity extends TopiaEntity - * @param entity used to load the property - * @param property name of the property in the entity - * @return a TopiaEntity corresponding to the property loaded - * @throws TopiaException for error on query execution - */ - protected <T extends TopiaEntity> TopiaEntity loadEntityProperty(T entity, - String property) - throws TopiaException { - return (TopiaEntity) loadProperty(entity, property); - } - - /** - * Load a property from an entity. - * - * @param <T> type of the entity extends TopiaEntity - * @param entity used to load the property - * @param property name of the property in the entity - * @return an Object corresponding to the property loaded - * @throws TopiaException for error loading property (encapsulate - * IllegalACessException, InvocationTargetException, - * NoSuchMethodException) - */ - protected <T extends TopiaEntity> Object loadProperty(T entity, - String property) - throws TopiaException { - try { - Object res = PropertyUtils.getProperty(entity, property); - if (log.isDebugEnabled()) { - log.debug("load property '" + property + "' for '" + - entity.getClass().getSimpleName() + "'"); - } - if (res != null && Collection.class.isAssignableFrom(res.getClass())) { - Collection<?> list = (Collection<?>) res; - list.size(); - } - return res; - } catch (IllegalAccessException eee) { - throw new TopiaException("Illegal access on property " + - property + " from entity " + - entity.getClass().getName(), eee); - } catch (InvocationTargetException eee) { - throw new TopiaException("Invocation error on entity " + - entity.getClass().getName() + " for property " + - property, eee); - } catch (NoSuchMethodException eee) { - throw new TopiaException("Getter method does not exist for" + - " property " + property + " from entity " + - entity.getClass().getName(), eee); - } - } - - /** - * This method is used to concat properties from entities. Ex in HQL you can - * have boat.shipOwner.name, these properties are defined as constants in - * each entity associated (SHIP_OWNER in Boat entity, NAME in ShipOwner - * entity) so you just have to call this method as : - * <pre> - * getProperty("boat", Boat.SHIP_OWNER, ShipOwner.NAME); - * // will return boat.shipOwner.name - * </pre> - * <p/> - * It's better to use constants instead of directly the string chain to - * avoid problems on changing property name in model. Furthermore it's - * better to use this method instead of doing : - * <pre> - * "boat." + Boat.SHIP_OWNER + "." + ShipOwner.NAME - * </pre> - * - * @param entityProperty to concat - * @return the string chain with properties separated with a dot - */ - public static String getProperty(String... entityProperty) { - List<String> list = Arrays.asList(entityProperty); - String result = StringUtil.join(list, ".", false); - return result; - } - - public String getPropertyId(String alias) { - return getProperty(alias, TopiaEntity.PROPERTY_TOPIA_ID); - } - - public String getPropertyCreateDate(String alias) { - return getProperty(alias, TopiaEntity.PROPERTY_TOPIA_CREATE_DATE); - } - - public String getPropertyVersion(String alias) { - return getProperty(alias, TopiaEntity.PROPERTY_TOPIA_VERSION); - } - - @Override - protected void finalize() throws Throwable { - // Clean StringBuilder statements -// select = null; - from = null; -// where = null; -// orderBy = null; -// groupBy = null; - super.finalize(); - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(fullQuery()). - append("; (PARAMS : "). - append(getParams()). - append("); (LIMIT : "). - append(startIndex). - append(", "). - append(endIndex). - append(')'); - return result.toString(); - } - -} Deleted: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/QueryHelperTransformer.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/QueryHelperTransformer.java 2013-07-05 15:29:40 UTC (rev 2741) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/QueryHelperTransformer.java 2013-07-05 16:04:49 UTC (rev 2742) @@ -1,602 +0,0 @@ -/* - * #%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% - */ -package org.nuiton.topia.generator; - -import org.apache.commons.lang3.RandomStringUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.eugene.GeneratorUtil; -import org.nuiton.eugene.java.JavaBuilder; -import org.nuiton.eugene.java.ObjectModelTransformerToJava; -import org.nuiton.eugene.models.object.ObjectModel; -import org.nuiton.eugene.models.object.ObjectModelAssociationClass; -import org.nuiton.eugene.models.object.ObjectModelAttribute; -import org.nuiton.eugene.models.object.ObjectModelClass; -import org.nuiton.eugene.models.object.ObjectModelClassifier; -import org.nuiton.eugene.models.object.ObjectModelJavaModifier; -import org.nuiton.eugene.models.object.ObjectModelModifier; -import org.nuiton.eugene.models.object.ObjectModelOperation; -import org.nuiton.eugene.models.object.ObjectModelType; -import org.nuiton.topia.framework.TopiaQuery; -import org.nuiton.topia.persistence.TopiaEntity; - -import java.util.HashMap; -import java.util.Map; - -/** - * Created: 23 juin 2010 - * - * @author fdesbois <fdesbois@codelutin.com> - * @version $Id$ - * @since 2.4 - * @plexus.component role="org.nuiton.eugene.Template" role-hint="org.nuiton.topia.generator.QueryHelperTransformer" - */ -public class QueryHelperTransformer extends ObjectModelTransformerToJava { - - private static final Log log = LogFactory.getLog(QueryHelperTransformer.class); - - protected ObjectModelClass helperClass; - - protected ObjectModelClass abstractEntityPropertyClass; - - protected static final String ENTITY_PROPERTY_CLASS_NAME = "EntityProperty"; - - protected static final String ENTITY_PROPERTY_SUFFIX = "Property"; - - protected static final String ENTITY_PROPERTY_GENERIC_TYPE = "<E>"; - - protected String mainException; - - protected Map<String, String> aliases; - - public static final String CONSTANT_PREFIX = "ALIAS_"; - - /*************************** MAIN PART OF THE HELPER **********************/ - - @Override - public void transformFromModel(ObjectModel model) { - - aliases = new HashMap<String, String>(); - - String modelName = StringUtils.capitalize(model.getName()); - String packageName = getOutputProperties().getProperty(PROP_DEFAULT_PACKAGE); - helperClass = createClass(modelName + "QueryHelper", packageName); - - addImport(helperClass, TopiaQuery.class); - addImport(helperClass, TopiaEntity.class); - - String exception = TopiaGeneratorUtil.getExceptionClassTagValue(model); - if (exception != null) { - addImport(helperClass, exception); - mainException = TopiaGeneratorUtil.getSimpleName(exception); - } - - initConstantPrefixFromModel(); - - createInnerAbstractEntityPropertyClass(); - createUtilOperations(); - } - - protected void createInnerAbstractEntityPropertyClass() { - - abstractEntityPropertyClass = (ObjectModelClass)addInnerClassifier(helperClass, - ObjectModelType.OBJECT_MODEL_CLASS, - ENTITY_PROPERTY_CLASS_NAME + ENTITY_PROPERTY_GENERIC_TYPE, - ObjectModelJavaModifier.ABSTRACT, - ObjectModelJavaModifier.STATIC); - - addImport(helperClass, HashMap.class); - addImport(helperClass, Map.class); - - addAttribute(abstractEntityPropertyClass, "alias", - String.class, null, - ObjectModelJavaModifier.PROTECTED); - - addAttribute(abstractEntityPropertyClass, "propertiesCache", - "Map<String, String>", null, - ObjectModelJavaModifier.PROTECTED); - - // Constructor - // FIXME-fdesbois-2010-06-23 : need to take care of generic case in JavaBuilder in EUGene -// ObjectModelOperation constructor = -// addConstructor(abstractEntityPropertyClass, ObjectModelJavaModifier.PUBLIC); - ObjectModelOperation constructor = - builder.addOperation(abstractEntityPropertyClass, ENTITY_PROPERTY_CLASS_NAME, null, ObjectModelJavaModifier.PUBLIC); - - setOperationBody(constructor, "" - /*{ - propertiesCache = new HashMap<String, String>(); - }*/ - ); - - // Getter and setter for alias - ObjectModelOperation setAlias = - addOperation(abstractEntityPropertyClass, "setAlias", "void", - ObjectModelJavaModifier.PROTECTED); - addParameter(setAlias, String.class, "alias"); - - - setOperationBody(setAlias, "" - /*{ - this.alias = alias; - }*/ - ); - - ObjectModelOperation getAlias = - addOperation(abstractEntityPropertyClass, "$alias", String.class, - ObjectModelJavaModifier.PUBLIC); - - - setOperationBody(getAlias, "" - /*{ - return alias; - }*/ - ); - - // Getter for properties - ObjectModelOperation getProperty = - addOperation(abstractEntityPropertyClass, "$property", String.class, - ObjectModelJavaModifier.PUBLIC); - addParameter(getProperty, String.class, "propertyName"); - - - setOperationBody(getProperty, "" - /*{ - String result = propertiesCache.get(propertyName); - if (result == null) { - result = TopiaQuery.getProperty(alias, propertyName); - propertiesCache.put(propertyName, result); - } - return result; - }*/ - ); - - ObjectModelOperation topiaCreateDate = - addOperation(abstractEntityPropertyClass, "topiaCreateDate", String.class, - ObjectModelJavaModifier.PUBLIC); - - setOperationBody(topiaCreateDate, "" - /*{ - return $property(TopiaEntity.PROPERTY_TOPIA_CREATE_DATE); - }*/ - ); - - ObjectModelOperation topiaId = - addOperation(abstractEntityPropertyClass, "topiaId", String.class, - ObjectModelJavaModifier.PUBLIC); - - setOperationBody(topiaId, "" - /*{ - return $property(TopiaEntity.PROPERTY_TOPIA_ID); - }*/ - ); - - ObjectModelOperation topiaVersion = - addOperation(abstractEntityPropertyClass, "topiaVersion", String.class, - ObjectModelJavaModifier.PUBLIC); - - setOperationBody(topiaVersion, "" - /*{ - return $property(TopiaEntity.PROPERTY_TOPIA_VERSION); - }*/ - ); - - // Abstract methods - addOperation(abstractEntityPropertyClass, "getEntityClass", - "Class" + ENTITY_PROPERTY_GENERIC_TYPE, - ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.ABSTRACT); - - addOperation(abstractEntityPropertyClass, "defaultAlias", String.class, - ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.ABSTRACT); - } - - protected void createUtilOperations() { - - // createQuery method with EntityProperty in argument - ObjectModelOperation createQuery = - addOperation(helperClass, "createQuery", TopiaQuery.class, - ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC); - addParameter(createQuery, ENTITY_PROPERTY_CLASS_NAME, "property"); - - setOperationBody(createQuery, "" - /*{ - return new TopiaQuery((Class<? extends TopiaEntity>)property.getEntityClass(), property.$alias()); - }*/ - ); - - // format method to format statement using $1, $2 corresponding to property names - ObjectModelOperation format = - addOperation(helperClass, "format", String.class, - ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC); - addParameter(format, String.class, "statement"); - addParameter(format, "String...", "propertyNames"); - - setOperationBody(format, "" - /*{ - for (int i = 1; i <= propertyNames.length; i++) { - statement = statement.replace("$" + i, propertyNames[i-1]); - } - return statement; - }*/ - ); - - // Methods to instantiate EntityProperty - String genericType = "<P extends " + ENTITY_PROPERTY_CLASS_NAME + "> P"; - ObjectModelOperation newEntityProperty1 = - addOperation(helperClass, "newEntityProperty", genericType, - ObjectModelJavaModifier.PRIVATE, ObjectModelJavaModifier.STATIC); - addParameter(newEntityProperty1, "Class<P>", "propertyClass"); - - setOperationBody(newEntityProperty1, "" - /*{ - return newEntityProperty(propertyClass, null); - }*/ - ); - ObjectModelOperation newEntityProperty2 = - addOperation(helperClass, "newEntityProperty", genericType, - ObjectModelJavaModifier.PRIVATE, ObjectModelJavaModifier.STATIC); - addParameter(newEntityProperty2, "Class<P>", "propertyClass"); - addParameter(newEntityProperty2, String.class, "alias"); - - StringBuilder buffer = new StringBuilder("" - /*{ - try { - P property = propertyClass.newInstance(); - if (alias == null) { - alias = property.defaultAlias(); - } - property.setAlias(alias); - return property; - } catch (Exception eee) { - }*/ - ); - - if (mainException != null) { - addException(newEntityProperty1, mainException); - addException(newEntityProperty2, mainException); - buffer.append("" - /*{ - throw new <%=mainException%>("Error instantiate " + propertyClass.getName(), eee); - }*/ - ); - } else { - buffer.append("" - /*{ - throw new Error("Error instantiate " + propertyClass.getName(), eee); - }*/ - ); - } - buffer.append("" - /*{ - } - }*/ - ); - - setOperationBody(newEntityProperty2, buffer.toString()); - } - - /*************************** INNER PROPERTY CLASSES ***********************/ - - @Override -// public void transformFromClass(ObjectModelClass clazz) { - public void transformFromClassifier(ObjectModelClassifier clazz) { - if (!TopiaGeneratorUtil.hasEntityStereotype(clazz)) { - return; - } - - // Create default alias for this entity - String aliasConstant = createAliasConstant(clazz.getName()); - - // Create inner class for this entity - ObjectModelClass entityPropertyClass = createInnerClass(clazz, aliasConstant); - - // Create methods to instantiate the inner class - createNewOperations(entityPropertyClass); - - addExtraForSubEntity(clazz); - } - - protected String createAliasConstant(String entityName) { - - String constantName = - TopiaGeneratorUtil.convertVariableNameToConstantName(entityName); - - String[] words = constantName.split("_"); - String alias = ""; - // Use first letter of each word as alias - for (String word : words) { - alias += word.substring(0, 1); - } - - // Case of existing alias, check other letters in lastWord - String lastWord = words[words.length - 1]; - while(aliases.containsKey(alias)) { - // Remove first letter - lastWord = lastWord.substring(1, lastWord.length()); - if (!lastWord.isEmpty()) { - // Use first letter of new lastWord to concat the alias - alias += lastWord.charAt(0); - } else { - // Generate an alea char to concat - alias += StringUtils.upperCase(RandomStringUtils.randomAlphabetic(1)); - } - } - - String aliasPropertyName = CONSTANT_PREFIX + constantName; - - if (log.isDebugEnabled()) { - log.debug("Add alias '" + alias + "' named " + aliasPropertyName); - } - - aliases.put(alias, aliasPropertyName); - - addAttribute(helperClass, aliasPropertyName, String.class, "\"" + alias + "\"", - ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC, ObjectModelJavaModifier.FINAL); - - return aliasPropertyName; - } - - protected ObjectModelClass createInnerClass(ObjectModelClassifier input, String aliasConstant) { - String className = getPropertyClassName(input); - - ObjectModelClass propertyClass = (ObjectModelClass) - addInnerClassifier(helperClass, - ObjectModelType.OBJECT_MODEL_CLASS, - className, - ObjectModelJavaModifier.STATIC); - - if (log.isDebugEnabled()) { - log.debug("Generate for entity : " + input.getQualifiedName()); - } - - // FIXME-fdesbois-2010-06-23 : need to manage imports for inner classes : EUGene ImportsManager - addImport(helperClass, input.getQualifiedName()); - - // Important to keep qualifiedName for setSuperClass - String superClassQualifiedName = abstractEntityPropertyClass.getQualifiedName(). - replace(ENTITY_PROPERTY_GENERIC_TYPE, "<" + input.getName() + ">"); - - setSuperClass(propertyClass, superClassQualifiedName); - - ObjectModelOperation constructor = - addConstructor(propertyClass, ObjectModelJavaModifier.PROTECTED); - - setOperationBody(constructor, "" - /*{ - }*/ - ); - - ObjectModelOperation getEntityClass = - addOperation(propertyClass, "getEntityClass", "Class<" + input.getName() + ">", - ObjectModelJavaModifier.PUBLIC); - - addAnnotation(propertyClass, getEntityClass, "Override"); - - setOperationBody(getEntityClass, "" - /*{ - return <%=input.getName()%>.class; - }*/ - ); - - ObjectModelOperation defaultAlias = - addOperation(propertyClass, "defaultAlias", String.class, - ObjectModelJavaModifier.PUBLIC); - - addAnnotation(propertyClass, defaultAlias, "Override"); - - setOperationBody(defaultAlias, "" - /*{ - return <%=aliasConstant%>; - }*/ - ); - - createGetterOperations(input, propertyClass); - - return propertyClass; - } - - protected void createGetterOperations(ObjectModelClassifier input, ObjectModelClass propertyClass) { - - // Generate for all attributes - for (ObjectModelAttribute attr : input.getAttributes()) { - - // Case we don't want generation for - if (!attr.isNavigable()) { - continue; - } - - String attrName = getReferenceAttributeName(attr); - - if (log.isDebugEnabled()) { - log.debug("Entity property : name=" + attrName + - " _ navigable=" + attr.isNavigable() + - " _ maxMultiplicity=" + attr.getMaxMultiplicity() + - " _ associationClass=" + attr.hasAssociationClass() + - " _ referenceClassifier=" + attr.referenceClassifier()); - } - - ObjectModelOperation propertyNameOperation = - createGetPropertyNameOperation(propertyClass, attrName, input.getName()); - - createGetPropertyObjectOperation(propertyClass, attr, propertyNameOperation); - } - - // Case of Association class : generate also for participant properties - if (input instanceof ObjectModelAssociationClass) { - - ObjectModelAssociationClass assoc = (ObjectModelAssociationClass)input; - - for (ObjectModelAttribute attr : assoc.getParticipantsAttributes()) { - ObjectModelOperation propertyNameOperation = - createGetPropertyNameOperation(propertyClass, attr.getName(), input.getName()); - - createGetPropertyObjectOperation(propertyClass, attr, propertyNameOperation); - } - } - } - - protected ObjectModelOperation createGetPropertyNameOperation(ObjectModelClass output, String attrName, String entityClassName) { - ObjectModelOperation result = - addOperation(output, attrName, String.class, ObjectModelJavaModifier.PUBLIC); - - String constantName = - entityClassName + "." + getConstantName(attrName); - - if (log.isDebugEnabled()) { - log.debug("Add getter for property : " + attrName + - " _ constantName = " + constantName + - " _ constantPrefix = " + getConstantPrefix()); - } - - setOperationBody(result, "" - /*{ - return $property(<%=constantName%>); - }*/ - ); - - return result; - } - - protected ObjectModelOperation createGetPropertyObjectOperation(ObjectModelClass output, - ObjectModelAttribute attrReference, - ObjectModelOperation propertyNameOperation) { - - ObjectModelClassifier referenceClass = getReferenceAttributeClassifier(attrReference); - - // No reference, can't add method to getPropertyObject - // ANO-#1648: Enum are ignored here, they will be used as simple property - if (referenceClass == null || referenceClass.isEnum()) { - return null; - } - - String operationName = getReferenceAttributeName(attrReference) + - ENTITY_PROPERTY_SUFFIX; - - String referencePropertyClassName = getPropertyClassName(referenceClass); - - ObjectModelOperation result = - addOperation(output, operationName, referencePropertyClassName); - - if (log.isDebugEnabled()) { - log.debug("Extra operation : " + operationName + - " _ className = " + referencePropertyClassName); - } - - setOperationBody(result, "" - /*{ - return new<%=referencePropertyClassName%>(<%=propertyNameOperation.getName()%>()); - }*/ - ); - - return result; - } - - protected void createNewOperations(ObjectModelClass entityProperty) { - - String className = entityProperty.getName(); - - String methodName = "new" + className; - - ObjectModelOperation newEntityProperty1 = - addOperation(helperClass, "new" + className, className, - ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC); - - setOperationBody(newEntityProperty1, "" - /*{ - return <%=methodName%>(null); - }*/ - ); - - ObjectModelOperation newEntityProperty2 = - addOperation(helperClass, "new" + className, className, - ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC); - addParameter(newEntityProperty2, String.class, "alias"); - - setOperationBody(newEntityProperty2, "" - /*{ - return newEntityProperty(<%=className%>.class, alias); - }*/ - ); - } - - protected void addExtraForSubEntity(ObjectModelClassifier entityClass) { - for (ObjectModelAttribute attr : entityClass.getAttributes()) { - - if (attr.isNavigable() && attr.referenceClassifier() && - attr.getClassifier().getName().equals(entityClass.getName())) { - // Same entity - - String propertyClassName = getPropertyClassName(entityClass); - - String subEntityName = entityClass.getName() + StringUtils.capitalize(attr.getName()); - String aliasConstant = createAliasConstant(subEntityName); - - ObjectModelOperation newEntityProperty = - addOperation(helperClass, "new" + subEntityName + "Property", propertyClassName, - ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC); - - String callMethodName = "new" + propertyClassName; - - setOperationBody(newEntityProperty, "" - /*{ - return <%=callMethodName%>(<%=aliasConstant%>); - }*/ - ); - - } - } - } - - // Helpers - protected String getPropertyClassName(ObjectModelClassifier entityClass) { - return entityClass.getName() + ENTITY_PROPERTY_SUFFIX; - } - - protected String getReferenceAttributeName(ObjectModelAttribute attrReference) { - String attrName = attrReference.getName(); - if(attrReference.hasAssociationClass()) { - attrName = GeneratorUtil.getAssocAttrName(attrReference); - } - return attrName; - } - - protected ObjectModelClassifier getReferenceAttributeClassifier(ObjectModelAttribute attrReference) { - ObjectModelClassifier referenceClass = null; - // case for attribute classifier, only for maxMultiplicity = 1 - if (attrReference.referenceClassifier() && attrReference.getMaxMultiplicity() == 1) { - referenceClass = attrReference.getClassifier(); - // case for association attribute - } else if (attrReference.hasAssociationClass()) { - referenceClass = attrReference.getAssociationClass(); - } - return referenceClass; - } - - // For tests - protected void setBuilder(JavaBuilder builder) { - this.builder = builder; - } -} 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-07-05 15:29:40 UTC (rev 2741) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaDAO.java 2013-07-05 16:04:49 UTC (rev 2742) @@ -43,6 +43,7 @@ import org.nuiton.topia.generator.EntityDAOTransformer; import org.nuiton.topia.persistence.pager.TopiaPagerBean; +import java.security.Permission; import java.util.List; import java.util.Map; @@ -60,7 +61,7 @@ * @author tchemit <chemit@codelutin.com> * @version $Id$ */ -public interface TopiaDAO<E extends TopiaEntity> extends TopiaDAODeprecated<E>, Iterable<E> { +public interface TopiaDAO<E extends TopiaEntity> extends Iterable<E> { //------------------------------------------------------------------------// //-- Create - update - delete methods ------------------------------------// @@ -685,5 +686,17 @@ void removeTopiaEntityVetoable(TopiaEntityVetoable vetoable); + /** + * Retourne les permissions a verifier pour l'acces a l'entite pour le + * service Taas. + * + * @param topiaId topiaId d'une entite + * @param actions encoded actions + * @return la liste des permissions + * @throws TopiaException if any pb while getting datas + * @deprecated since 2.6.14, {@link TopiaQuery} will be removed in version 3.0 + */ + List<Permission> getRequestPermission(String topiaId, int actions) + throws TopiaException; } //TopiaDAO Deleted: trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaDAODeprecated.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaDAODeprecated.java 2013-07-05 15:29:40 UTC (rev 2741) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaDAODeprecated.java 2013-07-05 16:04:49 UTC (rev 2742) @@ -1,169 +0,0 @@ -package org.nuiton.topia.persistence; -/* - * #%L - * ToPIA :: Persistence - * $Id$ - * $HeadURL$ - * %% - * Copyright (C) 2004 - 2012 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% - */ - -import org.nuiton.topia.TopiaContext; -import org.nuiton.topia.TopiaException; -import org.nuiton.topia.framework.TopiaQuery; - -import java.security.Permission; -import java.util.List; -import java.util.Map; - -/** - * Contains all method that are deprecated from {@link TopiaDAO} in version - * {@code 2.6.12} and then will be removed in next major version ({@code 3.0}). - * - * @author tchemit <chemit@codelutin.com> - * @since 2.6.12 - */ -public interface TopiaDAODeprecated<E extends TopiaEntity> { - - /** - * Crée une requete basé sur l'entité lié au DAO. Résultat attendu : "FROM - * E" - * - * @return une nouvelle TopiaQuery vide. (uniquement avec le From sur le - * type d'entité) - * @since 2.3 - * @deprecated since 2.6.12, {@link TopiaQuery} will be removed in version 3.0 - */ - @Deprecated - TopiaQuery createQuery(); - - /** - * Crée une requête basé sur l'entité lié au DAO et lui assigne un alias - * valable dans la requête.. - * <p/> - * Résultat attendu : "FROM E AS entityAlias" - * - * @param entityAlias alias permettant de manipuler l'entité dans la - * requête - * @return une nouvelle TopiaQuery - * @since 2.3 - * @deprecated since 2.6.12, {@link TopiaQuery} will be removed in version 3.0 - */ - @Deprecated - TopiaQuery createQuery(String entityAlias); - - /** - * Execute une requête basé sur l'entité du DAO. Permet de récupérer une - * entité correspondant à la requête. - * - * @param query la requête - * @return l'entité correspondant à la recherche ou null si aucune entité - * n'a été trouvée - * @throws TopiaException if any pb while getting datas - * @see TopiaQuery#executeToEntity(TopiaContext, Class) - * @since 2.3 - * @deprecated since 2.6.12, {@link TopiaQuery} will be removed in version 3.0 - */ - @Deprecated - E findByQuery(TopiaQuery query) throws TopiaException; - - /** - * Execute une requête basé sur l'entité du DAO. Permet de récupérer une - * liste d'entités correspondant à la requête. - * - * @param query la requête - * @return la liste d'entités correspondant à la recherche - * @throws TopiaException if any pb while getting datas - * @see TopiaQuery#executeToEntityList(TopiaContext, Class) - * @since 2.3 - * @deprecated since 2.6.12, {@link TopiaQuery} will be removed in version 3.0 - */ - @Deprecated - List<E> findAllByQuery(TopiaQuery query) throws TopiaException; - - /** - * Execute une requête basé sur l'entité du DAO. Permet de récupérer une map - * d'entités correspondant à la requête. La clé de la map étant le topiaId - * de l'entité. - * - * @param query la requête - * @return la map d'entités correspondant à la recherche - * @throws TopiaException if any pb while getting datas - * @see TopiaQuery#executeToEntityMap(TopiaContext, Class) - * @since 2.3 - * @deprecated since 2.6.12, {@link TopiaQuery} will be removed in version 3.0 - */ - @Deprecated - Map<String, E> findAllMappedByQuery(TopiaQuery query) throws TopiaException; - - /** - * Execute une requête basé sur l'entité du DAO. Permet de récupérer une map - * d'entités correspondant à la requête. Le type et le nom de la propriété - * utilisé comme clé de la map doit être passé en argument. - * - * @param <K> type de la clé de la map - * @param query la requête - * @param keyName nom de la propriété de l'entité utilisée comme clé - * @param keyClass type de la propriété de l'entité utilisée comme clé - * @return la map d'entités correspondant à la recherche - * @throws TopiaException if any pb while getting datas - * @see TopiaQuery#executeToEntityMap(TopiaContext, Class) - * @since 2.3 - * @deprecated since 2.6.12, {@link TopiaQuery} will be removed in version 3.0 - */ - @Deprecated - <K> Map<K, E> findAllMappedByQuery(TopiaQuery query, - String keyName, Class<K> keyClass) throws TopiaException; - - /** - * Check the existence of an entity using a {@code query}. - * - * @param query query used to test existence - * @return true if entity exists, false otherwise - * @throws TopiaException - * @since 2.3.4 - * @deprecated since 2.6.12, {@link TopiaQuery} will be removed in version 3.0 - */ - @Deprecated - boolean existByQuery(TopiaQuery query) throws TopiaException; - - /** - * Count the number of entities based on {@code query}. - * - * @param query query - * @return number of entities filtered by the query - * @throws TopiaException if any pb while getting datas - * @since 2.3.4 - * @deprecated since 2.6.12, {@link TopiaQuery} will be removed in version 3.0 - */ - @Deprecated - int countByQuery(TopiaQuery query) throws TopiaException; - - /** - * Retourne les permissions a verifier pour l'acces a l'entite pour le - * service Taas. - * - * @param topiaId topiaId d'une entite - * @param actions encoded actions - * @return la liste des permissions - * @throws TopiaException if any pb while getting datas - * @deprecated since 2.6.14, {@link TopiaQuery} will be removed in version 3.0 - */ - List<Permission> getRequestPermission(String topiaId, int actions) - throws TopiaException; -} 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-07-05 15:29:40 UTC (rev 2741) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/TopiaDAOImpl.java 2013-07-05 16:04:49 UTC (rev 2742) @@ -39,18 +39,24 @@ import com.google.common.base.Preconditions; 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.Criteria; +import org.hibernate.FlushMode; import org.hibernate.HibernateException; import org.hibernate.Session; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.Order; +import org.hibernate.criterion.Projections; +import org.hibernate.criterion.Restrictions; import org.hibernate.metadata.ClassMetadata; import org.nuiton.topia.TopiaException; import org.nuiton.topia.event.TopiaEntityListener; import org.nuiton.topia.event.TopiaEntityVetoable; import org.nuiton.topia.framework.TopiaContextImplementor; -import org.nuiton.topia.framework.TopiaQuery; import org.nuiton.topia.persistence.pager.TopiaPagerBean; import org.nuiton.util.PagerBeanUtil; @@ -126,6 +132,46 @@ this.batchSize = batchSize; } + private E query(Criterion criterion) throws TopiaException { + try { + Criteria criteria = createCriteria(FlushMode.AUTO); + criteria.add(criterion); + criteria.setMaxResults(1); + List<E> result = (List<E>) criteria.list(); + int sizeBefore = result != null ? result.size() : 0; + result = getContext().getFiresSupport().fireEntitiesLoad(context, result); + int sizeAfter = result != null ? result.size() : 0; + if (sizeAfter < sizeBefore) { + if (log.isDebugEnabled()) { + log.debug((sizeBefore - sizeAfter) + + " element(s) removed. Filter entity: " + + entityClass.getName() + " - criterion: " + + criterion); + } + } + if (result != null && result.size() > 0) { + E elem = result.get(0); + return elem; + } + return null; + } catch (HibernateException eee) { + throw new TopiaException(eee); + } + } + + /** + * Renvoie un Criteria créé avec l'entityClass + * + * @param mode le FlushMode du Criteria + * @return le Criteria nouvellement créé + * @throws TopiaException if any pb + */ + private Criteria createCriteria(FlushMode mode) throws TopiaException { + Criteria criteria = getSession().createCriteria(entityClass); + criteria.setFlushMode(mode); + return criteria; + } + @Override public Iterator<E> iterator() { @@ -390,24 +436,8 @@ } @Override - public TopiaQuery createQuery() { - return new TopiaQuery(getEntityClass()); - } - - @Override - public TopiaQuery createQuery(String entityAlias) { - return new TopiaQuery(getEntityClass(), entityAlias); - } - - @Override public E findByTopiaId(String id) throws TopiaException { - // Nothing to do if id is null, the result will still be null. - E result = null; - if (id != null) { - TopiaQuery query = createQuery().addEquals(TopiaEntity.PROPERTY_TOPIA_ID, id); - result = findByQuery(query); - } - return result; + return query(Restrictions.idEq(id)); } @Override @@ -431,28 +461,26 @@ @Override public E findByProperties(Map<String, Object> properties) throws TopiaException { - TopiaQuery query = createQuery().addEquals(properties); - E result = findByQuery(query); - return result; + return query(Restrictions.allEq(properties)); } @Override - public E findByQuery(TopiaQuery query) throws TopiaException { - E result = query.executeToEntity(getContext(), getEntityClass()); - return result; - } - - @Override public List<E> findAll() throws TopiaException { - List<E> results = findAllByQuery(createQuery()); - return results; + try { + Criteria criteria = createCriteria(FlushMode.AUTO); + List<E> result = (List<E>) criteria.list(); + result = getContext().getFiresSupport().fireEntitiesLoad(context, + result); + return result; + } catch (HibernateException eee) { + throw new TopiaException(eee); + } } @Override public List<String> findAllIds() throws TopiaException { - TopiaQuery query = createQuery().setSelect(TopiaEntity.PROPERTY_TOPIA_ID); - List<String> results = getContext().findByQuery(query); - return results; + List<String> find = context.findAll("select src.topiaId from " + getEntityClass().getName() + " src"); + return find; } @Override @@ -476,59 +504,53 @@ @Override public List<E> findAllByProperties(Map<String, Object> properties) throws TopiaException { - TopiaQuery query = createQuery().addEquals(properties); - List<E> results = findAllByQuery(query); - return results; + return queryAll(Restrictions.allEq(properties)); } - @Override - public List<E> findAllByQuery(TopiaQuery query) throws TopiaException { - List<E> results = query.executeToEntityList(getContext(), getEntityClass()); - return results; + private List<E> queryAll(Criterion criterion) throws TopiaException { + try { + Criteria criteria = createCriteria(FlushMode.AUTO); + criteria.add(criterion); + List<E> result = (List<E>) criteria.list(); + result = getContext().getFiresSupport().fireEntitiesLoad(context, + result); + return result; + } catch (HibernateException eee) { + throw new TopiaException(eee); + } } @Override - public Map<String, E> findAllMappedByQuery(TopiaQuery query) - throws TopiaException { - Map<String, E> results = - query.executeToEntityMap(getContext(), getEntityClass()); - return results; - } - - @Override - public <K> Map<K, E> findAllMappedByQuery(TopiaQuery query, String keyName, - Class<K> keyClass) - throws TopiaException { - Map<K, E> results = - query.executeToEntityMap(getContext(), getEntityClass(), - keyName, keyClass); - return results; - } - - @Override public List<E> findAllWithOrder(String... propertyNames) throws TopiaException { - TopiaQuery query = createQuery().addOrder(propertyNames); - List<E> results = findAllByQuery(query); - return results; + try { + Criteria criteria = createCriteria(FlushMode.AUTO); + for (String propertyName : propertyNames) { + criteria.addOrder(Order.asc(propertyName)); + } + List<E> result = (List<E>) criteria.list(); + result = getContext().getFiresSupport().fireEntitiesLoad(context, + result); + return result; + } catch (HibernateException eee) { + throw new TopiaException(eee); + } } @Override public E findContains(String propertyName, Object property) throws TopiaException { - TopiaQuery k = createQuery(). - addInElements(":K", propertyName). - addParam("K", property); - return findByQuery(k); + E find = (E)context.findUnique("from " + getEntityClass().getName() + + " WHERE :property in elements(" + propertyName + ")", "property", property); + return find; } @Override public List<E> findAllContains(String propertyName, Object property) throws TopiaException { - TopiaQuery k = createQuery(). - addInElements(":K", propertyName). - addParam("K", property); - return findAllByQuery(k); + List<E> find = (List<E>)context.findAll("from " + getEntityClass().getName() + + " WHERE :property in elements(" + propertyName + ")", "property", property); + return find; } @Override @@ -542,30 +564,32 @@ Object... others) throws TopiaException { Map<String, Object> properties = convertPropertiesArrayToMap(propertyName, propertyValue, others); - TopiaQuery query = createQuery().addEquals(properties); - boolean result = existByQuery(query); + boolean result = false; + try { + Criteria criteria = createCriteria(FlushMode.AUTO); + criteria.add(Restrictions.allEq(properties)); + criteria.setProjection(Projections.rowCount()); + Number count = (Number) criteria.uniqueResult(); + result = count.intValue() > 0; + } catch (HibernateException eee) { + throw new TopiaException(eee); + } return result; } @Override - public boolean existByQuery(TopiaQuery query) throws TopiaException { - int count = countByQuery(query); - boolean result = count > 0; - return result; - } - - @Override public long count() throws TopiaException { - int result = countByQuery(createQuery()); + long result = -1; + try { + Criteria criteria = createCriteria(FlushMode.AUTO); + criteria.setProjection(Projections.rowCount()); + result = ((Number)criteria.uniqueResult()).longValue(); + } catch (HibernateException eee) { + throw new TopiaException(eee); + } return result; } - @Override - public int countByQuery(TopiaQuery query) throws TopiaException { - int result = query.executeCount(getContext()); - return result; - } - /** * Convert a properties array to a proper map used to find entities in * methods {@link #findByProperties(String, Object, Object...)} and {@link Deleted: trunk/topia-persistence/src/site/rst/user/TopiaQuery.rst =================================================================== --- trunk/topia-persistence/src/site/rst/user/TopiaQuery.rst 2013-07-05 15:29:40 UTC (rev 2741) +++ trunk/topia-persistence/src/site/rst/user/TopiaQuery.rst 2013-07-05 16:04:49 UTC (rev 2742) @@ -1,544 +0,0 @@ -.. - -.. * #%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% -.. - - -TopiaQuery -========== - -:Author: Florian Desbois -:Contact: topia-devel@list.nuiton.org ou topia-users@list.nuiton.org -:Revision: $Revision$ -:Date: $Date$ - -L'objet TopiaQuery permet de créer plus simplement des requêtes HQL pour éviter -les concaténations complexes lors de l'utilisation de la méthode **find** -du TopiaContext. - -Chacune des parties de la requête sont indépendantes et seront concaténés au -moment de l'exécution. Il est donc possible d'ajouter des éléments à la -requête à n'importe quel moment de sa construction (from, select, where, order, -group, ...). - -La TopiaQuery peut donc être construite à un endroit et exécutée à un autre. -Une même requête peut également être réutilisée pour être passée en sous-requête -ou exécutée plusieurs fois à la suite avec certains légers changement de -paramètres. - -.. contents:: - -Modèle exemple --------------- - -Ci-dessous un modèle simple utilisé pour les exemples de cette documentation. - -.. image:: modelForTopiaQuery.png - -Instantiation -------------- - -La TopiaQuery nécessite obligatoirement une entité référence pour être exécutée. -Cette entité correspondra à l'élément principal du FROM de la requête et si -nécessaire sera ajouté automatiquement au SELECT. - -Il y a plusieurs façons d'instancier la TopiaQuery : - -Directement depuis un DAO :: - - TopiaContext transaction = rootContext.beginTransaction(); - BoatDAO dao = ModelDAOHelper.getBoatDAO(transaction); - TopiaQuery query = dao.createQuery(); - -ou depuis un topiaContext :: - - TopiaContext transaction = rootContext.beginTransaction(); - TopiaQuery query = transaction.createQuery(Boat.class, "B"); - -L'intérêt de passer par un DAO est de pouvoir par la suite executer la requête -avec ce même DAO. Il est également possible d'utiliser des alias pour l'élément -principal de la requête pour pouvoir plus facilement gérer les cas de jointure. -Il suffit de préciser l'alias au moment de l'instanciation :: - - TopiaContext transaction = rootContext.beginTransaction(); - BoatDAO dao = ModelDAOHelper.getBoatDAO(transaction); - TopiaQuery query = dao.createQuery("E"); - -Ajout d'éléments au WHERE -------------------------- - -Les méthodes de base nécessaires concernent l'ajout d'élements dans le WHERE de la -requête. Plusieurs méthodes sont disponibles suivant les besoins pour ajouter -simplement un élément au where :: - - TopiaQuery query = boatDAO.createQuery(); - - // Recherche sur l'immatriculation du navire : immatriculation = 142154 - query.addEquals("immatriculation", 142154); - - // Recherche toutes les dates de construction < 2006 - query.addWhere("buildYear", Op.LT, 2006); - - // Recherche des navires ayant un nom - query.addNotNull("name"); - - // depuis 2.3.4 - // Recherche des navires n'ayant pas de nom - query.addNull("name"); - - // Recherche des navires ayant une date de construction 2003, 2004 ou 2006 - query.addEquals("buildYear", 2003, 2004, 2006); - - // depuis 2.3.4 - // Recherche entre deux dates - TopiaQuery queryContact = contactDAO.createQuery(); - Calendar dateBegin = new GregorianCalendar(2010,2,3); - Calendar dateEnd = new GregorianCalendar(2010,5,6); - queryContact.addBetween("creationDate", dateBegin.getTime(), dateEnd.getTime()); - - // depuis 2.3.4 - // Utilisation d'une sous-requête (les paramètres de la sous-requête seront - // ajoutés automatiquement à la requête principale en gérant les doublons - // (sur la valeur et la clé)). - // Le ? correspond à l'endroit ou sera injecté la requête, attention aux - // parenthèses. - queryContact.addSubQuery("boat IN elements(?)", query); - -Il est fortement conseillé d'utiliser les constantes des entités pour les noms -de leurs propriétés :: - - query.addEquals(Boat.IMMATRICULATION, 142154); - query.addNotNull(Boat.NAME); - ... - -La TopiaQuery peut être chaînée, les méthodes permettant l'ajout d'éléments -renvoient toutes la même TopiaQuery avec l'élément ajouté :: - - TopiaContext transaction = rootContext.beginTransaction(); - BoatDAO dao = ModelDAOHelper.getBoatDAO(transaction); - dao.createQuery().addEquals(Boat.IMMATRICULATION, 142154).addNotNull(Boat.NAME); - -Opérateurs ----------- - -Une enum interne à la TopiaQuery permet de manipuler les opérateurs nécessaires -aux ajouts dans le WHERE : - -- TopiaQuery.Op.EQ : Opérateur = -- TopiaQuery.Op.GT : Opérateur > -- TopiaQuery.Op.GE : Opérateur >= -- TopiaQuery.Op.LIKE : Opérateur LIKE -- TopiaQuery.Op.LT : Opérateur < -- TopiaQuery.Op.LE : Opérateur <= -- TopiaQuery.Op.NOT_NULL : Opérateur IS NOT NULL -- TopiaQuery.Op.NULL : Opérateur IS NULL -- TopiaQuery.Op.NEQ : Opérateur != - -Autres parties de la requête ----------------------------- - -Ajout d'élément au FROM -~~~~~~~~~~~~~~~~~~~~~~~ - -Il est souvent nécessaire d'ajouter une autre entité au FROM de la requête, -pour ce faire, il existe deux méthodes : - -- addFrom(Class entityClass) : ajoute une entité au FROM - (Ex : addFrom(Contact.class);) - -- addFrom(Class entityClass, String alias) : ajoute une entité au FROM avec un - alias (Ex : addFrom(Contact.class, "C");) - -C'est généralement la dernière méthode qui sera la plus utilisé, l'utilisation -des alias facilitant grandement les liaisons entre les entités. - -Depuis la 2.3.4, deux méthodes ont été rajoutés pour le cas des jointures : - -- addJoin(Class entityClass, String alias, boolean fetch) : utilise un inner - join pour lier une entité à celle de la requête. Concrètement l'opérateur - JOIN Hql sera utilisé : 'FROM Contact C JOIN C.boat' :: - - TopiaContext transaction = rootContext.beginTransaction(); - ContactDAO dao = ModelDAOHelper.getBoatDAO(transaction); - TopiaQuery query = dao.createQuery("C").addJoin("C.boat", null, false); - -- addLeftJoin(Class entityClass, String alias, boolean fetch) : même chose que - le addJoin sauf que l'opérateur LEFT JOIN Hql sera utilisé. - - -Voir le `Chargement des donnees` pour l'utilisation du fetch. - -Ajout d'élément au SELECT -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Deux méthodes sont disponibles pour le cas du SELECT, une méthode addSelect -qui se chargera d'ajouter une propriété au SELECT, et une méthode setSelect -qui définira directement quel est le SELECT souhaité. Pour le cas du addSelect, -la méthode gère automatiquement l'entité principale utilisé pour instancier -la requête, il n'est donc pas nécessaire de l'ajouter manuellement. - -TODO : find an example - -Le setSelect quant à lui est utilisé pour les aggregations par exemple ou -pour récupérer des parties précises du résultat :: - - TopiaContext transaction = rootContext.beginTransaction(); - BoatDAO dao = ModelDAOHelper.getBoatDAO(transaction); - // On souhaite connaître le nombre de résultats uniquement - TopiaQuery query = dao.createQuery(). - addNotNull(Boat.NAME). - setSelect("COUNT(*)"); - -autre exemple :: - - // On souhaite récupérer uniquement les noms des navires - TopiaQuery query = dao.createQuery(). - addNotNull(Boat.NAME). - setSelect(Boat.NAME); - -Note - Pour l'ajout d'une contrainte sur l'unicité des résultats, vous pouvez - utiliser la méthode addDistinct() qui permet l'ajout du mot clé DISTINCT sur - le SELECT de la requête. - -Ajout d'élément au GROUP BY -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Dans certains cas, il peut être nécessaire d'utiliser un GROUP BY -pour les aggregations :: - - TopiaContext transaction = rootContext.beginTransaction(); - ContactDAO dao = ModelDAOHelper.getContactDAO(transaction); - // On souhaite connaître le nombre de contacts par navire - TopiaQuery query = dao.createQuery(). - setSelect("COUNT(*)"). - addGroup(Contact.BOAT); - -Ajout d'élément au ORDER BY -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Il est possible également d'ajouter un ordre aux résultats :: - - TopiaContext transaction = rootContext.beginTransaction(); - BoatDAO dao = ModelDAOHelper.getBoatDAO(transaction); - // Tous les noms des navires triés - TopiaQuery query = dao.createQuery(). - addNotNull(Boat.NAME). - setSelect(Boat.NAME). - addOrder(Boat.NAME); - -Une autre méthode est disponible pour l'ordre descendant : addOrderDesc. -Cependant rien ne vous interdit la syntaxe suivante :: - - addOrder(Boat.NAME, Boat.BUILD_YEAR + " desc"); - -Requête complexe ----------------- - -L'intérêt majeur de la TopiaQuery est de pouvoir la manipuler à travers des -méthodes tout en lui ajoutant des éléments suivant certaines conditions. -Il peut être également utile d'utiliser une TopiaQuery comme sous-requête d'une -autre. De plus certains mots clés comme EXISTS ou encore l'utilisation de -méthode HQL ne possèdent pas leurs propres méthodes. Vous pouvez cependant -utiliser la méthode de base **addWhere(String str)** qui permet l'ajout au WHERE -directement (avec ajout automatique des parenthèses). Dans ce cas, il est -souvent nécessaire d'ajouter des paramètres HQL à la requête (:monParam) qui -devront être ajouté à la TopiaQuery en utilisant la méthode -**addParam(String name, Object value)**. Ex :: - - TopiaContext transaction = rootContext.beginTransaction(); - ContactDAO dao = ModelDAOHelper.getContactDAO(transaction); - Date beginDate = ... - Date endDate = ... - TopiaQuery query1 = dao.createQuery("C"). - addWhere("C." + Contact.VALIDATION + " IS NOT NULL OR " + - "C." + Contact.CREATION_DATE + " BETWEEN :begin AND :end"). - addParam("begin", beginDate).addParam("end", endDate); - -La méthode **fullQuery()** permettra de récupérer la requête sous forme -de chaîne pour pouvoir la manipuler comme sous-requête. Il est possible -également de récupérer les paramètres via la méthode **getParams()** pour -les rajouter à la requête global :: - - // suite du code précédent - // On souhaite la date de création la plus récente sur la requête précédente - query1.setSelect("MAX(C." + Contact.CREATION_DATE + ")"); - - // Préparation de la deuxième requête - TopiaQuery query2 = dao.createQuery("C2"); - - // sélection spécifique pour un navire - if (immatriculation != null) { - query2.addEquals("C2." + Contact.BOAT + "." + Boat.IMMATRICULATION, - immatriculation); - - // Ajout d'une condition sur le navire dans la première requête - query1.addWhere("C." + Contact.BOAT + " = C2." + Contact.BOAT); - } - - // Utilisation de la première requête comme sous-requête - query2.add("C2." + Contact.CREATION_DATE + " = (" + query1.fullQuery() + ")"); - // Ajout des paramètres nécessaires de la première requête dans la deuxième - query2.addParams(query1.getParams()); - -Depuis la 2.3.4, la méthode **addSubQuery(String statement, TopiaQuery subquery)** -permet de faciliter l'injection d'une sous-requête notamment pour la gestion -des paramètres automatiquement (avec prise en charge des doublons) :: - - // Même chose que précédemment en utilisant la méthode addSubQuery - query2.addSubQuery("C2." + Contact.CREATION_DATE + " = (?)", query1); - -La requête sous forme HQL :: - - SELECT C2 FROM Contact C2 - WHERE C2.boat.immatriculation = :immatriculation - AND C2.creationDate = (SELECT MAX(C.creationDate) FROM Contact C - WHERE (C.validation IS NOT NULL OR - C.creationDate BETWEEN :begin AND :end) - AND C.boat = C2.boat); - -Attention - Il ne faut pas utiliser la méthode addEquals(String str, Object value) pour - une comparaison entre deux propriétés comme précédemment : - *query1.addWhere("C." + Contact.BOAT + " = C2." + Contact.BOAT)*. - L'appel *query1.addEquals("C." + Contact.BOAT, "C2." + Contact.BOAT)* ne - fonctionnera pas comme souhaité. - -Résultats ---------- - -Plusieurs méthodes sont disponibles pour récupérer les résultats de la requête. -Pour chaque méthode, il est nécessaire de l'appeler avec le contexte -topia. La méthode de base est la méthode execute() qui renvoie -une liste non typé à l'instar de la méthode find(...) du TopiaContext. Il -est cependant possible de récupérer directement un objet, un entier (pour -un aggregat par exemple) ou une chaîne de caractères suivant le select de la -requête. Pour le count très utile dans de nombreux cas, il est mis à disposition -la méthode **executeCount()** qui se chargera de remplacer temporairement le -select par un COUNT(*). L'avantage c'est que votre requête ne perd pas son -SELECT d'origine pour pouvoir être par exemple executé de façon différente par -la suite. - -Note - Si la requête contient un DISTINCT (via la méthode addDistinct()), le - executeCount() gèrera automatiquement la contrainte sur la requête : - "SELECT COUNT(DISTINCT B) FROM Boat B ..." - -Limitation des résultats -~~~~~~~~~~~~~~~~~~~~~~~~ - -Il est possible de limiter le nombre de résultats lors de l'exécution pour -optimiser la requête dans le cas d'une pagination par exemple. Pour ce faire -il faut utiliser les méthodes **setLimit(int start, int end)** et/ou -**setMaxResults(int max)** :: - - // 18 premiers résultats - query.setLimit(0, 17); - // équivalent à - query.setMaxResults(18); - // résultats du 50ème au 60ème - query.setLimit(49, 59); - -// depuis 2.3.4 - -Pour éviter d'embarquer ces paramètres à chaque fois qu'ils sont nécessaires -lors d'un filtrage paginée, un bean, *EntityFilter* est disponible. -Il contient les attributs suivants : - -- startIndex : index de début des résultats. - -- endIndex : index de fin des résultats. - -- orderBy : propriétés à ordonner (l'ajout des mots clés 'asc' et 'desc' est - possible). - -- referenceId : identifiant d'une référence utile à la requête. - -- referenceProperty : nom de la propriété correspondant à la valeur du referenceId. - -Exemple : Nous souhaitons les contacts 30 à 60 triés par 'creationDate' décroissant et -'personName' croissant pour un navire donné par son topiaId :: - - EntityFilter filter = new EntityFilter(); - filter.setStartIndex(30); - filter.setEndIndex(60); - filter.setOrderBy("creationDate desc, personName"); - filter.setReferenceId(boat.getTopiaId()); - // ou filter.setReference(boat); - filter.setReferenceProperty("boat"); - - TopiaQuery query = contactDAO.createQuery().addFilter(filter); - -L'intérêt de l'EntityFilter est de pouvoir l'instancier et le manipuler directement -depuis votre interface (Swing, Web, ...) et de l'utiliser sur une requête métier. -La méthode **addFilter(EntityFilter filter)** permettra d'injecter les paramètres -s'ils possèdent une valeur. - -Note - L'ordre définit par défaut est celui de création par ordre décroissant : - *topiaCreateDate desc*. - -Utilisation des DAO -~~~~~~~~~~~~~~~~~~~ - -Les DAO fournissent également quelques méthodes permettant de récupérer plus -facilement les résultats avec le type souhaité : - -- **countByQuery(TopiaQuery query)** : compte le nombre de résultats de la - requête. -- **existByQuery(TopiaQuery query)** : renvoie vrai si la requête à retourner - au moins 1 résultat. -- **findByQuery(TopiaQuery query)** : renvoie une entité (un seul résultat) -- **findAllByQuery(TopiaQuery query)** : renvoie une liste d'entités -- **findAllMappedByQuery(TopiaQuery query)** : renvoie une map d'entités avec - pour clé le topiaId de l'entité. -- **findAllMappedByQuery(TopiaQuery query, Class keyClass, String keyProperty)** : - renvoie une map d'entités avec pour clé la propriété passée en argument. - -Exemple :: - - TopiaContext transaction = rootContext.beginTransaction(); - BoatDAO dao = ModelDAOHelper.getBoatDAO(transaction); - TopiaQuery query = dao.createQuery(); - ... - // pour vérifier l'existance de résultat - boolean hasResult = dao.existByQuery(query); - - // pour savoir le nombre de résultats - int count = dao.countByQuery(query); - - // pour récupérer les résultats - Map<String, Boat> boatMap = dao.findAllMappedByQuery(query); - // ou - List<Boat> boatList = dao.findAllByQuery(query); - // ou juste le premier résultat - Boat boat = dao.findByQuery(query); - // ou avec pour clé l'immatriculation du navire (unique) - Map<Integer, Boat> boatMapImma = dao.findAllMappedByQuery(query, - Integer.class, Boat.IMMATRICULATION); - - -Résultats complexes -~~~~~~~~~~~~~~~~~~~ - -Certains cas de requête peuvent avoir des résultats plus complexes, notamment -lorsqu'il s'agit de propriétés de différentes entités ou avec l'utilisation d' -aggrégats (AVG, SUM, COUNT). Dans ce cas il faut utiliser la méthode de base -**findByQuery(TopiaQuery query)** depuis une transaction -qui renverra une liste non typée. Lorsqu'il y a plus d'un élément dans le -select la liste renvoyée est une List<Object[]>, le tableau pour chaque ligne -correspondant aux valeurs des résultats. Exemple :: - - TopiaContext transaction = rootContext.beginTransaction(); - ContactDAO dao = ModelDAOHelper.getContactDAO(transaction); - String boatImma = Contact.BOAT + "." + Boat.IMMATRICULATION; - // On souhaite le nombre de contacts par navire - TopiaQuery query = dao.createQuery(). - setSelect(boatImma, "COUNT(*)").addGroup(boatImma); - - List<Object[]> results = transaction.findByQuery(query); - // Parcours des résultats - for (Object[] result : results) { - Integer immatriculation = (Integer)result[0]; - Long count = (Long)result[1]; - } - -Note - Les aggrégats renvoient principalement un type Long et non Integer. - -Chargement des donnees ----------------------- - -Généralement une fois la requête exécutée, la transaction utilisée est directement -fermée (topiaContext.closeContext()). Dans ce cas, il est souvent nécessaire de -charger certaines entités pour éviter les malencontreuses LazyException d'Hibernate. -Plusieurs possibilités s'offrent à vous : - -Chargement automatique -~~~~~~~~~~~~~~~~~~~~~~ - -Hibernate permet de déclarer explicitement que certaines relations doivent se -charger dès la récupération des entités. Il faut pour cela utiliser le tagValue -*lazy* dans le fichier de properties du modèle. Par exemple pour charger -le navire associé à chaque contact récupéré via une requête, il faut préciser :: - - myapp.entity.Contact.attribute.boat.tagvalue.lazy=false - -(*myapp.entity.Contact* étant le nom qualifié de la classe Contact) - -Ainsi chaque contact récupéré aura automatiquement son navire associé de chargé. - -**Attention** cependant, il ne faut pas abuser du tagvalue *lazy* car sinon Hibernate -risque de charger une bonne partie de votre base de données à chaque fois, ce qui -peut s'avérer extrêment coûteux. Cette utilisation doit être limitée au cas d'une -simple association comme c'est ici le cas, le Boat chargé étant **indispensable** -à l'utilisation du Contact. - -Chargement manuel -~~~~~~~~~~~~~~~~~ - -La TopiaQuery fournit deux méthodes intéressantes pour le chargement manuelle : - - - addLoad(String...) : permet de charger les relations une fois la requête - exécutée. - - - addFetch(String...) : permet de charger les relations directement au moment - de la requête en utilisant une jointure et le mot clé 'FETCH' Hql. - -Le addLoad est pour le moment limité à des relations unitaires (autant que votre -modèle vous le permet, ex : entityA.entityB.entityC) ou à une seule relation -multiple directe ou indirecte (entityA.entitiesB). Si nous prenons le cas du -modèle d'exemple, il est possible de charger le navire associé aux contacts en -utilisant : queryContact.addLoad(Contact.BOAT); - -Dans le cas du addLoad, plusieurs requêtes seront exécutées suivant le nombre -de Contact résultats. Il est dans ce cas plus judicieux d'utiliser le addFetch -qui chargera directement les Boat au moment de la récupération des Contact : -queryContact.addFetch(Contact.BOAT); L'alias peut s'avérer indispensable pour -l'utilisation du addFetch, voir la javadoc pour l'utilisation des arguments. - -Note - Les méthodes de jointures permettent de faire un fetch directement : - addJoin(String property, String alias, boolean fetch); - Voir la partie de la documentation concernant le FROM de la requête. - -Attention - Hibernate ne supporte pas plus de 3 ou 4 jointures suivant leurs complexités ! - Il est donc important de limiter l'utilisation des fetch aux cas simples. - -Que choisir ? -~~~~~~~~~~~~~ - -- Relation unitaire (N-1) obligatoire : utiliser le tagValue *lazy* - -- Requête relativement simple (moins de deux jointures) : utiliser le addFetch - -- Requête complexe : utiliser le addLoad - -- Si addLoad non utilisable (trop de chargement de collections) : effectuer un - chargement manuel en parcourant les résultats. Pour le chargement d'une - entité simple, il suffit d'utiliser le getter correspondant pour la charger, - tandis que pour une collection, l'appel à la méthode size associée permet de - charger l'intégralité des éléments. - - - Deleted: trunk/topia-persistence/src/test/java/org/nuiton/topia/framework/TopiaQueryTest.java =================================================================== --- trunk/topia-persistence/src/test/java/org/nuiton/topia/framework/TopiaQueryTest.java 2013-07-05 15:29:40 UTC (rev 2741) +++ trunk/topia-persistence/src/test/java/org/nuiton/topia/framework/TopiaQueryTest.java 2013-07-05 16:04:49 UTC (rev 2742) @@ -1,189 +0,0 @@ -/* - * #%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% - */ - -package org.nuiton.topia.framework; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Assert; -import org.junit.Test; -import org.nuiton.topia.persistence.TopiaEntity; -import org.nuiton.topiatest.QueriedEntity; - -/** @author fdesbois */ -public class TopiaQueryTest { - - private static final Log log = LogFactory.getLog(TopiaQueryTest.class); - - @Test - public void testAdd() { - - // Test with one paramValue - String value = "topia"; - TopiaQuery query = new TopiaQuery(QueriedEntity.class); - query.addEquals(QueriedEntity.PROPERTY_TEST_ADD, value); - Assert.assertEquals( - "FROM org.nuiton.topiatest.QueriedEntity " + - "WHERE testAdd = :testAdd", - query.fullQuery()); - - // Test with null paramValue - //String nullValue = null; - query = new TopiaQuery(QueriedEntity.class); - query.addEquals(QueriedEntity.PROPERTY_TEST_ADD, new Object[]{null}); - Assert.assertEquals( - "FROM org.nuiton.topiatest.QueriedEntity " + - "WHERE testAdd IS NULL", - query.fullQuery()); - - // Test with two paramValues - String value2 = "eugene"; - query = new TopiaQuery(QueriedEntity.class); - query.addEquals(QueriedEntity.PROPERTY_TEST_ADD, value, value2); - Assert.assertEquals( - "FROM org.nuiton.topiatest.QueriedEntity " + - "WHERE testAdd IN (:testAdd1, :testAdd2)", - query.fullQuery()); - - // Test with two paramValues + null - query = new TopiaQuery(QueriedEntity.class); - query.addEquals(QueriedEntity.PROPERTY_TEST_ADD, value, value2, null); - Assert.assertEquals( - "FROM org.nuiton.topiatest.QueriedEntity " + - "WHERE testAdd IN (:testAdd1, :testAdd2) OR testAdd IS NULL", - query.fullQuery()); - } - - @Test - public void testAddSubQuery() { - - // Test 1 : Subquery with two params with different values - TopiaQuery query = new TopiaQuery(QueriedEntity.class). - addEquals(QueriedEntity.PROPERTY_TEST_ADD, "value1"); - // Exist 2 params - Assert.assertEquals(2, query.getParams().size()); - - TopiaQuery subquery = new TopiaQuery(QueriedEntity.class). - addEquals(QueriedEntity.PROPERTY_TEST_ADD, "value2"); - - query.addSubQuery("Q1 = (?)", subquery); - log.debug(query); - // Add other params from subquery - Assert.assertEquals(4, query.getParams().size()); - - - // Test 2 : Subquery with two params with different values - // one of them is null - query = new TopiaQuery(QueriedEntity.class). - addWhere(QueriedEntity.PROPERTY_TEST_ADD, TopiaQuery.Op.EQ, null); - // Exist 0 param (null value) - Assert.assertEquals(0, query.getParams().size()); - - subquery = new TopiaQuery(QueriedEntity.class). - addEquals(QueriedEntity.PROPERTY_TEST_ADD, "value1"); - - query.addSubQuery("Q1 = (?)", subquery); - log.debug(query); - // Add 2 params from subquery - Assert.assertEquals(2, query.getParams().size()); - - - // Test 3 : Subquery with two params with same value - query = new TopiaQuery(QueriedEntity.class, "Q1"). - addEquals(QueriedEntity.PROPERTY_TEST_ADD, "value1"); - // Exist 2 params - Assert.assertEquals(2, query.getParams().size()); - - subquery = new TopiaQuery(QueriedEntity.class, "Q2"). - addEquals(QueriedEntity.PROPERTY_TEST_ADD, "value1"); - - query.addSubQuery("Q1 = (?)", subquery); - log.debug(query); - // Still 2 params - Assert.assertEquals(2, query.getParams().size()); - - // non-regression test, when parameters of main query is not empty - // and sub-query use different parameters from the one used in the - // main query, parameters needed by the subquery are lost in the - // resulting query - - // Test 4 : add a subquery with its own parameters - query = new TopiaQuery(QueriedEntity.class, "Q1"). - addEquals(QueriedEntity.PROPERTY_TOPIA_ID, "ID1"); - - subquery = new TopiaQuery(QueriedEntity.class, "Q2"). - addEquals(QueriedEntity.PROPERTY_TEST_ADD, "value"); - - query.addSubQuery(QueriedEntity.PROPERTY_TEST_ADD + " IN (?)", subquery); - - log.debug(query); - Assert.assertEquals(4, query.getParams().size()); - } - - /** Test of addFilter method, of class TopiaQuery. */ - @Test - public void testAddFilter() { - log.info("testAddFilter"); - - EntityFilter filter = new TopiaFilter(); - filter.setStartIndex(1); - filter.setEndIndex(40); - filter.setOrderBy(QueriedEntity.PROPERTY_TEST_ADD); - - TopiaQuery query = new TopiaQuery(QueriedEntity.class).addFilter(filter); - - log.debug("Query : " + query); - - Assert.assertEquals("FROM " + QueriedEntity.class.getName() + - " ORDER BY " + QueriedEntity.PROPERTY_TEST_ADD, - query.fullQuery()); - - filter.setOrderBy(null); - - query = new TopiaQuery(QueriedEntity.class).addFilter(filter); - - log.debug("Query : " + query); - - Assert.assertEquals("FROM " + QueriedEntity.class.getName() + - " ORDER BY " + TopiaEntity.PROPERTY_TOPIA_CREATE_DATE + " DESC", - query.fullQuery()); - - } - - @Test - // cf http://nuiton.org/issues/1745 - public void testWhereWithFunction() { - - TopiaQuery query = new TopiaQuery(QueriedEntity.class); - query.addWhere("lower(name)", TopiaQuery.Op.LIKE, "%azerty%"); - - log.debug("Query : " + query); - - Assert.assertEquals("FROM " + QueriedEntity.class.getName() + - " WHERE lower(name) LIKE :lower_name_", - query.fullQuery()); - } - -} Deleted: trunk/topia-persistence/src/test/java/org/nuiton/topia/generator/QueryHelperTransformerTest.java =================================================================== --- trunk/topia-persistence/src/test/java/org/nuiton/topia/generator/QueryHelperTransformerTest.java 2013-07-05 15:29:40 UTC (rev 2741) +++ trunk/topia-persistence/src/test/java/org/nuiton/topia/generator/QueryHelperTransformerTest.java 2013-07-05 16:04:49 UTC (rev 2742) @@ -1,68 +0,0 @@ -/* - * #%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% - */ -package org.nuiton.topia.generator; - -import org.junit.Assert; -import org.junit.Test; -import org.nuiton.eugene.java.JavaBuilder; -import org.nuiton.eugene.models.object.xml.ObjectModelClassImpl; - -import java.util.HashMap; - -/** - * Created: 24 juin 2010 - * - * @author fdesbois <fdesbois@codelutin.com> - * @version $Id$ - */ -public class QueryHelperTransformerTest { - - @Test - public void testCreateAliasConstant() { - QueryHelperTransformer transformer = new QueryHelperTransformer(); - transformer.aliases = new HashMap<String, String>(); - transformer.helperClass = new ObjectModelClassImpl(); - transformer.setBuilder(new JavaBuilder("TopiaTest")); - - String entityName = "Department"; - transformer.createAliasConstant(entityName); - Assert.assertEquals(1, transformer.aliases.size()); - Assert.assertTrue(transformer.aliases.containsKey("D")); - - entityName = "Depot"; - transformer.createAliasConstant(entityName); - Assert.assertEquals(2, transformer.aliases.size()); - Assert.assertTrue(transformer.aliases.containsKey("DE")); - - entityName = "Deposite"; - transformer.createAliasConstant(entityName); - Assert.assertEquals(3, transformer.aliases.size()); - Assert.assertTrue(transformer.aliases.containsKey("DEP")); - - entityName = "Dep"; - transformer.createAliasConstant(entityName); - Assert.assertEquals(4, transformer.aliases.size()); - } -}
participants (1)
-
echatellier@users.nuiton.org