r1271 - in trunk: wikitty-api/src/main/java/org/nuiton/wikitty wikitty-api/src/main/java/org/nuiton/wikitty/query wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions wikitty-api/src/main/java/org/nuiton/wikitty/storage wikitty-api/src/test/java/org/nuiton/wikitty/storage wikitty-solr/src/main/java/org/nuiton/wikitty/storage/solr wikitty-solr/src/test/java/org/nuiton/wikitty/storage/solr
Author: bpoussin Date: 2011-12-31 15:06:23 +0100 (Sat, 31 Dec 2011) New Revision: 1271 Url: http://nuiton.org/repositories/revision/wikitty/1271 Log: Evolution #1863: Create new query api with visitor and better implementation Evolution #1864: Add query langage syntaxe - implantation du select en condition ce qui permet de faire des jointures facilement avec le In (tout semble fini, reste a nettoyer un peu et ajouter plus de tests) Added: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions/Select.java trunk/wikitty-solr/src/test/java/org/nuiton/wikitty/storage/solr/WikittySearchEngineSolrForQueryTest.java Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyClient.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQuery.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryMaker.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryParser.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryVisitor.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryVisitorCopy.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryVisitorToString.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions/Condition.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions/ConditionNary.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions/ConditionUnary.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions/In.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/storage/WikittySearchEngine.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/storage/WikittySearchEngineInMemory.java trunk/wikitty-api/src/test/java/org/nuiton/wikitty/storage/WikittySearchEngineInMemoryTest.java trunk/wikitty-solr/src/main/java/org/nuiton/wikitty/storage/solr/WikittyQueryVisitorToSolr.java trunk/wikitty-solr/src/main/java/org/nuiton/wikitty/storage/solr/WikittySearchEngineSolr.java Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyClient.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyClient.java 2011-12-30 15:50:02 UTC (rev 1270) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyClient.java 2011-12-31 14:06:23 UTC (rev 1271) @@ -26,7 +26,7 @@ import java.util.Collections; import java.util.Date; import java.util.HashMap; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -39,6 +39,7 @@ import org.nuiton.wikitty.query.WikittyQueryResult; import org.nuiton.wikitty.query.WikittyQueryResultTreeNode; import org.nuiton.wikitty.query.conditions.ElementField; +import org.nuiton.wikitty.query.conditions.Select; /** * Wikitty client is object used in client side to access WikittyService. @@ -173,22 +174,28 @@ this.wikittyService = new WikittyServiceEnhanced(wikittyService); } - public <E extends BusinessEntity> E store(E e) { - Wikitty w = ((BusinessEntityImpl)e).getWikitty(); - store(w); - return e; - } + //////////////////////////////////////////////////////////////////////////// + // + // STORE + // + //////////////////////////////////////////////////////////////////////////// public Wikitty store(Wikitty w) { long start = TimeLog.getTime(); WikittyEvent resp = wikittyService.store(securityToken, w); // update object resp.update(w); - + timeLog.log(start, "store"); return w; } + public <E extends BusinessEntity> E store(E e) { + Wikitty w = ((BusinessEntityImpl)e).getWikitty(); + store(w); + return e; + } + public <E extends BusinessEntity> E[] store(E e1, E e2, E... eN) { List<E> es = new ArrayList<E>(eN.length + 2); Collections.addAll(es, e1, e2); @@ -258,61 +265,35 @@ return wikitties; } + //////////////////////////////////////////////////////////////////////////// + // + // RESTORE + // + //////////////////////////////////////////////////////////////////////////// + /** - * Restore wikitty entity with specified id or {@code null} if entity can't be found. - * - * @param <E> object type - * @param clazz entity class - * @param id entity id - * @param checkExtension if true check that Wikitty result has all extension - * declared in clazz + * Restore wikitty entity with specified id or {@code null} if entity can't be be found. + * + * @param id entity ids if null return is empty list * @return wikitty entity with specified id or {@code null} if entity can't be found */ - public <E extends BusinessEntity> E restore(Class<E> clazz, String id, boolean checkExtension) { - try { - long start = TimeLog.getTime(); - E result = null; - if (id != null) { - HashSet<String> extNames = null; + public List<Wikitty> restore(List<String> id) { + long start = TimeLog.getTime(); - Wikitty wikitty = wikittyService.restore(securityToken, id); - if (wikitty != null) { - if (checkExtension) { - extNames = new HashSet<String>(wikitty.getExtensionNames()); - } - result = WikittyUtil.newInstance( - securityToken, wikittyService, clazz, wikitty); - - if (checkExtension) { - // WikittyUtil.newInstance instanciate only BusinessEntityWikittyImpl - BusinessEntityImpl b = (BusinessEntityImpl) result; - Collection<WikittyExtension> BusinessEntityStaticExtensions = b.getStaticExtensions(); - for (WikittyExtension ext : BusinessEntityStaticExtensions) { - String extensionName = ext.getName(); - if (!extNames.contains(extensionName)) { - // extension wanted by BusinessEntity (clazz) - // is not in wikitty, then wikitty is not good type - // for business - result = null; - break; - } - } - } - } - } - - timeLog.log(start, "restore<Business>"); - return result; - } catch (SecurityException eee) { - throw eee; - } catch (Exception eee) { - throw new WikittyException("Can't restore wikitty", eee); + List<Wikitty> result; + if (id == null) { + result = new ArrayList<Wikitty>(); + } else { + result = wikittyService.restore(securityToken, id); } + + timeLog.log(start, "restore<list>"); + return result; } /** * Restore wikitty entity with specified id or {@code null} if entity can't be found. - * + * * @param id entity id * @return wikitty entity with specified id or {@code null} if entity can't be found */ @@ -320,47 +301,14 @@ long start = TimeLog.getTime(); Wikitty result = null; if (id != null) { - result = wikittyService.restore(securityToken, id); + result = restore(Collections.singletonList(id)).get(0); } - + timeLog.log(start, "restore"); - return result; - } - - /** - * Restore wikitty entity with specified id or {@code null} if entity can't be found. - * - * @param <E> object type - * @param clazz entity class - * @param id entity id - * @return wikitty entity with specified id or {@code null} if entity can't be found - */ - public <E extends BusinessEntity> E restore(Class<E> clazz, String id) { - E result = restore(clazz, id, false); return result; } /** - * Restore wikitty entity with specified id or {@code null} if entity can't be be found. - * - * @param id entity ids if null return is empty list - * @return wikitty entity with specified id or {@code null} if entity can't be found - */ - public List<Wikitty> restore(List<String> id) { - long start = TimeLog.getTime(); - - List<Wikitty> result; - if (id == null) { - result = new ArrayList<Wikitty>(); - } else { - result = wikittyService.restore(securityToken, id); - } - - timeLog.log(start, "restoreWikitty<list>"); - return result; - } - - /** * Restore wikitty entity with specified id or {@code null} if entity * can't be be found, or checkExtension is true and wikitty don't match * extension wanted. @@ -406,6 +354,40 @@ return result; } + /** + * Restore wikitty entity with specified id or {@code null} if entity can't be found. + * + * @param <E> object type + * @param clazz entity class + * @param id entity id + * @return wikitty entity with specified id or {@code null} if entity can't be found + */ + public <E extends BusinessEntity> E restore(Class<E> clazz, String id) { + E result = restore(clazz, id, false); + return result; + } + + /** + * Restore wikitty entity with specified id or {@code null} if entity can't be found. + * + * @param <E> object type + * @param clazz entity class + * @param id entity id + * @param checkExtension if true check that Wikitty result has all extension + * declared in clazz + * @return wikitty entity with specified id or {@code null} if entity can't be found + */ + public <E extends BusinessEntity> E restore(Class<E> clazz, String id, boolean checkExtension) { + long start = TimeLog.getTime(); + E result = null; + if (id != null) { + result = restore(clazz, Collections.singletonList(id), checkExtension).get(0); + } + + timeLog.log(start, "restore<Business>"); + return result; + } + public <E extends BusinessEntity> List<E> restore(Class<E> clazz, List<String> id) { List<E> result = restore(clazz, id, false); return result; @@ -417,7 +399,7 @@ list = new ArrayList<String>(id); } List<Wikitty> resultList = restore(list); - Set<Wikitty> result = new HashSet<Wikitty>(resultList); + Set<Wikitty> result = new LinkedHashSet<Wikitty>(resultList); return result; } @@ -432,10 +414,16 @@ list = new ArrayList<String>(id); } List<E> resultList = restore(clazz, list, checkExtension); - Set<E> result = new HashSet<E>(resultList); + Set<E> result = new LinkedHashSet<E>(resultList); return result; } + //////////////////////////////////////////////////////////////////////////// + // + // DETELE + // + //////////////////////////////////////////////////////////////////////////// + public void delete(String id) { long start = TimeLog.getTime(); wikittyService.delete(securityToken, id); @@ -477,6 +465,12 @@ timeLog.log(start, "delete<list<BusinessEntity>>"); } + /////////////////////////////////////////////////////////////////////////// + // + // FIND (ALL) BY EXEMPLE <E> + // + /////////////////////////////////////////////////////////////////////////// + /** * Null field are not used in search request. * @@ -494,7 +488,7 @@ .setFirst(first).setLimit(limit) .setFacetField(fieldFacet); - WikittyQueryResult<String> queryResult = findAllIdByQuery(query); + WikittyQueryResult<String> queryResult = findAllByQuery(query); WikittyQueryResult<E> result = (WikittyQueryResult<E>)castTo( e.getClass(), queryResult); @@ -512,7 +506,7 @@ long start = TimeLog.getTime(); WikittyQuery query = new WikittyQueryMaker().wikitty(e).end(); - String id = findIdByQuery(query); + String id = findByQuery(query); E result = (E)restore(e.getClass(), id); timeLog.log(start, "findByExample"); @@ -521,112 +515,171 @@ /////////////////////////////////////////////////////////////////////////// // - // FIND ALL BY CRITERIA <E> + // FIND ALL BY QUERY <E> // /////////////////////////////////////////////////////////////////////////// /** + * Cette method doit etre l'unique methode finalement utilise par toutes + * les methodes find avec un cast vers clazz + * * Search object that correspond to criteria and that have all extension - * needed by BusinessEntity (clazz). If one criteria is null, find all extensions - * for this criteria else if criteria is empty return nothing. - * + * needed by BusinessEntity (clazz), if clazz is BusinessEntity class. + * If one criteria is empty, find all extensions + * for this criteria else if criteria is null return null. + * * @param <E> object type + * Can be Wikitty, BusinessEntity, String, Date, Number (returned is BigDecimal), Boolean, byte[] * @param clazz entity class - * @param criterias criterias + * @param queries criterias + * @param limitToFirst if true limit result to first result (first = 0, limit = 1) * @return paged result */ - public <E extends BusinessEntity> List<WikittyQueryResult<E>> findAllByQuery( - Class<E> clazz, List<WikittyQuery> criterias) { + protected <E> List<WikittyQueryResult<E>> findAllByQuery( + Class<E> clazz, List<WikittyQuery> queries, boolean limitToFirst) { long start = TimeLog.getTime(); List<WikittyQueryResult<E>> result = null; - if (criterias != null) { - // newInstance only return BusinessEntityWikittyImpl - BusinessEntityImpl sample = - (BusinessEntityImpl) WikittyUtil.newInstance(clazz); + List<WikittyQuery> serviceQueries; + if (queries != null) { + if (clazz.isAssignableFrom(BusinessEntity.class)) { + // on demande un business entity donc on modifie + // pas les criteres pour ajouter les contraintes sur les + // extensions - Wikitty wikitty = sample.getWikitty(); - Collection<String> extensions = wikitty.getExtensionNames(); + // newInstance only return BusinessEntityWikittyImpl + BusinessEntityImpl sample = + (BusinessEntityImpl) WikittyUtil.newInstance((Class<BusinessEntity>)clazz); - List<WikittyQuery> serviceCriterias = new ArrayList<WikittyQuery>(criterias.size()); - for (WikittyQuery criteria : criterias) { + Wikitty wikitty = sample.getWikitty(); + Collection<String> extensions = wikitty.getExtensionNames(); - // on ajoute la condition sur les extensions dans le critere - // du coup, pour ne pas modifier le critere qui vient en parametre - // il faut creer un nouveau critere ... - WikittyQuery serviceCriteria = null; - if (criteria != null) { - serviceCriteria = criteria.copy(); + serviceQueries = new ArrayList<WikittyQuery>(queries.size()); + for (WikittyQuery criteria : queries) { - // Dont add contraint if using select - if (StringUtils.isEmpty(criteria.getSelect())) { + // on ajoute la condition sur les extensions dans le critere + // du coup, pour ne pas modifier le critere qui vient en parametre + // il faut creer un nouveau critere ... + WikittyQuery serviceQuery = null; + if (criteria != null) { + serviceQuery = criteria.copy(); + WikittyQueryMaker queryMaker; + if (serviceQuery.getCondition() instanceof Select) { + // si la condition commence par un select + // alors il faut modifier la condition du select + Select select = (Select)serviceQuery.getCondition(); + queryMaker = new WikittyQueryMaker() + .select(select.getElement()) + .and().condition(select.getSubCondition()) + .extContainsAll(extensions); + } else { + // sinon on modifie directement la condition + queryMaker = new WikittyQueryMaker() + .and().condition(serviceQuery.getCondition()) + .extContainsAll(extensions); + } // utilisation de cette nouvelle contrainte sur le nouvel objet - // creation de la nouvelle contrainte - WikittyQueryMaker queryMaker = new WikittyQueryMaker() - .and().condition(serviceCriteria.getCondition()) - .extContainsAll(extensions); - - serviceCriteria.setCondition(queryMaker.getCondition()); + serviceQuery.setCondition(queryMaker.getCondition()); } + + // ajout de ce criteria dans la liste de tous les criteres + serviceQueries.add(serviceQuery); } + } else { + // on ne demande pas un business entity donc on ne modifie + // pas les criteres + serviceQueries = queries; + } - // ajout de ce criteria dans la liste de tous les criteres - serviceCriterias.add(serviceCriteria); + if (limitToFirst) { + for (WikittyQuery query : serviceQueries) { + query.setFirst(0); + query.setLimit(1); + // lorsqu'on limit au premier, c'est qu'on utilise la methode + // pour retourne seulement un objet et pas un WikittyQueryResult + // on n'a donc pas a calculer les facets + query.setFacetExtension(false); + query.setFacetField(); + query.setFacetQuery(); + } } List<WikittyQueryResult<String>> pagedResult = wikittyService.findAllByQuery( - securityToken, serviceCriterias); + securityToken, serviceQueries); - // TODO poussin 20110318 optimize cast. Try to cast all pagedResult id - // in one call to service. Currently each PagedResult.cast do a call result = new ArrayList<WikittyQueryResult<E>>(pagedResult.size()); for (WikittyQueryResult<String> p : pagedResult) { - result.add((WikittyQueryResult<E>)castTo(sample.getClass(), p)); + result.add((WikittyQueryResult<E>)castTo(clazz, p)); } } - timeLog.log(start, "findAllByCriteria<Business>(List)"); + timeLog.log(start, "findAllByQuery<E>(List, limitToFirst)"); return result; } /** * Search object that correspond to criteria and that have all extension - * needed by BusinessEntity (clazz). If criteria is null, find all extensions - * else if criteria is empty return nothing. + * needed by BusinessEntity (clazz), if clazz is BusinessEntity class. + * If one criteria is empty, find all extensions + * for this criteria else if criteria is null return null. * * @param <E> object type + * Can be Wikitty, BusinessEntity, String, Date, Number (returned is BigDecimal), Boolean, byte[] * @param clazz entity class + * @param criterias criterias + * @return paged result + */ + public <E> List<WikittyQueryResult<E>> findAllByQuery( + Class<E> clazz, List<WikittyQuery> criterias) { + long start = TimeLog.getTime(); + List<WikittyQueryResult<E>> result = findAllByQuery(clazz, criterias, false); + timeLog.log(start, "findAllByQuery<E>(List)"); + return result; + } + + /** + * Search object that correspond to criteria and that have all extension + * needed by BusinessEntity (clazz), if clazz is BusinessEntity class. + * If one criteria is empty, find all extensions + * for this criteria else if criteria is null return null. + * + * @param <E> object type + * Can be Wikitty, BusinessEntity, String, Date, Number (returned is BigDecimal), Boolean, byte[] + * @param clazz entity class * @param criteria criteria * @return paged result */ - public <E extends BusinessEntity> WikittyQueryResult<E> findAllByCriteria( + public <E> WikittyQueryResult<E> findAllByQuery( Class<E> clazz, WikittyQuery criteria) { long start = TimeLog.getTime(); WikittyQueryResult<E> result = findAllByQuery(clazz, - Collections.singletonList(criteria)).get(0); - timeLog.log(start, "findAllByCriteria<Business>(One)"); + Collections.singletonList(criteria), false).get(0); + timeLog.log(start, "findAllByQuery<E>(One)"); return result; } /** + /** * Search object that correspond to criteria and that have all extension - * needed by BusinessEntity (clazz). If criteria is null, find all extensions - * else if criteria is empty return nothing. + * needed by BusinessEntity (clazz), if clazz is BusinessEntity class. + * If one criteria is empty, find all extensions + * for this criteria else if criteria is null return null. * * @param <E> object type + * Can be Wikitty, BusinessEntity, String, Date, Number (returned is BigDecimal), Boolean, byte[] * @param clazz entity class * @param c1 criteria 1 * @param c2 criteria 2 * @param otherCriteria otherCriteria * @return paged result */ - public <E extends BusinessEntity> WikittyQueryResult<E>[] findAllByQuery( + public <E> WikittyQueryResult<E>[] findAllByQuery( Class<E> clazz, WikittyQuery c1, WikittyQuery c2, WikittyQuery... otherCriteria) { long start = TimeLog.getTime(); List<WikittyQuery> criterias = new ArrayList<WikittyQuery>(otherCriteria.length + 2); Collections.addAll(criterias, c1, c2); Collections.addAll(criterias, otherCriteria); - List<WikittyQueryResult<E>> resultList = findAllByQuery(clazz, criterias); + List<WikittyQueryResult<E>> resultList = findAllByQuery(clazz, criterias, false); WikittyQueryResult<E>[] result = resultList.toArray(new WikittyQueryResult[criterias.size()]); timeLog.log(start, "findAllByCriteria<Business>(Varargs)"); return result; @@ -634,81 +687,81 @@ /////////////////////////////////////////////////////////////////////////// // - // FIND ALL BY CRITERIA <Wikitty> + // FIND BY CRITERIA <E> // /////////////////////////////////////////////////////////////////////////// - public List<WikittyQueryResult<Wikitty>> findAllByQuery(List<WikittyQuery> criteria) { + public <E> List<E> findByQuery(Class<E> clazz, List<WikittyQuery> criterias) { long start = TimeLog.getTime(); - List<WikittyQueryResult<Wikitty>> result = null; - if (criteria != null) { - List<WikittyQueryResult<String>> resultId = - wikittyService.findAllByQuery(securityToken, criteria); - // TODO poussin 20110318 optimize cast. Try to cast all pagedResult id - // in one call to service. Currently each PagedResult.cast do a call - result = new ArrayList<WikittyQueryResult<Wikitty>>(resultId.size()); - for (WikittyQueryResult<String> p : resultId) { - result.add(castTo(Wikitty.class, p)); + List<WikittyQueryResult<E>> queryResult = + findAllByQuery(clazz, criterias, true); + List<E> result = new ArrayList<E>(queryResult.size()); + for (WikittyQueryResult<E> r : queryResult) { + if (r.size() > 0) { + result.add(r.peek()); + } else { + result.add(null); } } - timeLog.log(start, "findAllByCriteria(List)"); - return result; + + timeLog.log(start, "multiFindByCriteria<E>(List>"); + return result; } - public WikittyQueryResult<Wikitty> findAllByQuery(WikittyQuery criteria) { + public <E> E findByQuery(Class<E> clazz, WikittyQuery criteria) { long start = TimeLog.getTime(); - WikittyQueryResult<Wikitty> result = null; + E result = null; if (criteria != null) { - result = findAllByQuery(Collections.singletonList(criteria)).get(0); + result = findByQuery(clazz, Collections.singletonList(criteria)).get(0); } - timeLog.log(start, "findAllByCriteria(One)"); - return result; + timeLog.log(start, "findByQuery<E>(One)"); + return result; } - public WikittyQueryResult<Wikitty>[] findAllByQuery( - WikittyQuery c1, WikittyQuery c2, WikittyQuery ... otherCriteria) { + public <E> E[] findByQuery( + Class<E> clazz, WikittyQuery c1, WikittyQuery c2, WikittyQuery... otherCriteria) { long start = TimeLog.getTime(); List<WikittyQuery> criterias = new ArrayList<WikittyQuery>(otherCriteria.length + 2); Collections.addAll(criterias, c1, c2); Collections.addAll(criterias, otherCriteria); - List<WikittyQueryResult<Wikitty>> resultList = findAllByQuery(criterias); - WikittyQueryResult<Wikitty>[] result = resultList.toArray(new WikittyQueryResult[criterias.size()]); + List<E> resultList = findByQuery(clazz, criterias); + E[] result = resultList.toArray((E[])Array.newInstance(clazz, resultList.size())); - timeLog.log(start, "findAllByCriteria(Varargs)"); - return result; + timeLog.log(start, "findByCriteria<E>(Varargs)"); + return result; } /////////////////////////////////////////////////////////////////////////// // - // FIND ALL ID BY CRITERIA <String> + // FIND ALL FIELD OR ID BY CRITERIA <String> // /////////////////////////////////////////////////////////////////////////// - public List<WikittyQueryResult<String>> findAllIdByQuery(List<WikittyQuery> criteria) { + public List<WikittyQueryResult<String>> findAllByQuery(List<WikittyQuery> criteria) { long start = TimeLog.getTime(); List<WikittyQueryResult<String>> result = null; if (criteria != null) { result = wikittyService.findAllByQuery(securityToken, criteria); } - timeLog.log(start, "findAllIdByCriteria(List)"); - return result; + timeLog.log(start, "findAllByCriteria(List)"); + return result; } - public WikittyQueryResult<String> findAllIdByQuery(WikittyQuery criteria) { + public WikittyQueryResult<String> findAllByQuery(WikittyQuery criteria) { long start = TimeLog.getTime(); WikittyQueryResult<String> result = null; if (criteria != null) { - result = findAllIdByQuery( + result = findAllByQuery( Collections.singletonList(criteria)).get(0); } - timeLog.log(start, "findAllIdByCriteria(One)"); + timeLog.log(start, "findAllByCriteria(One)"); return result; } - public WikittyQueryResult<String>[] findAllIdByQuery( + public WikittyQueryResult<String>[] findAllByQuery( WikittyQuery c1, WikittyQuery c2, WikittyQuery ... otherCriteria) { long start = TimeLog.getTime(); @@ -716,10 +769,10 @@ Collections.addAll(criterias, c1, c2); Collections.addAll(criterias, otherCriteria); - List<WikittyQueryResult<String>> resultList = findAllIdByQuery(criterias); + List<WikittyQueryResult<String>> resultList = findAllByQuery(criterias); WikittyQueryResult<String>[] result = resultList.toArray(new WikittyQueryResult[criterias.size()]); - timeLog.log(start, "findAllIdByCriteria(Varargs)"); + timeLog.log(start, "findAllByCriteria(Varargs)"); return result; } @@ -729,27 +782,27 @@ // /////////////////////////////////////////////////////////////////////////// - public List<String> findIdByQuery(List<WikittyQuery> criteria) { + public List<String> findByQuery(List<WikittyQuery> criteria) { long start = TimeLog.getTime(); List<String> result = null; if (criteria != null) { result = wikittyService.findByQuery(securityToken, criteria); } - timeLog.log(start, "findIdByCriteria(List)"); + timeLog.log(start, "findByCriteria(List)"); return result; } - public String findIdByQuery(WikittyQuery criteria) { + public String findByQuery(WikittyQuery criteria) { long start = TimeLog.getTime(); String result = null; if (criteria != null) { - result = findIdByQuery(Collections.singletonList(criteria)).get(0); + result = findByQuery(Collections.singletonList(criteria)).get(0); } - timeLog.log(start, "findIdByCriteria(One)"); + timeLog.log(start, "findByCriteria(One)"); return result; } - public String[] findIdByQuery( + public String[] findByQuery( WikittyQuery c1, WikittyQuery c2, WikittyQuery... otherCriteria) { long start = TimeLog.getTime(); @@ -757,121 +810,15 @@ Collections.addAll(criterias, c1, c2); Collections.addAll(criterias, otherCriteria); - List<String> resultList = findIdByQuery(criterias); + List<String> resultList = findByQuery(criterias); String[] result = resultList.toArray(new String[criterias.size()]); - timeLog.log(start, "findIdByCriteria(Varargs)"); - return result; - } - - /////////////////////////////////////////////////////////////////////////// - // - // FIND BY CRITERIA <E> - // - /////////////////////////////////////////////////////////////////////////// - - public <E extends BusinessEntity> List<E> findByQuery( - Class<E> clazz, List<WikittyQuery> criterias) { - long start = TimeLog.getTime(); - List<E> result = null; - if (criterias != null) { - BusinessEntityImpl sample = - (BusinessEntityImpl) WikittyUtil.newInstance(clazz); - - Wikitty wikitty = sample.getWikitty(); - Collection<String> extensions = wikitty.getExtensionNames(); - List<WikittyQuery> serviceCriterias = new ArrayList<WikittyQuery>(criterias.size()); - for (WikittyQuery criteria : criterias) { - // on a pas besoin de recuperer les limits du query puisqu'on en - // veut qu'un et donc qu'on ne retourne pas de WikittyQueryResult - // donc on ne fait pas une copie, on en cree un nouveau directement - // a partir de la condition - WikittyQuery q = new WikittyQueryMaker() - .and().condition(criteria.getCondition()) - .extContainsAll(extensions).end(); - serviceCriterias.add(q); - } - - List<String> id = findIdByQuery(serviceCriterias); - result = restore(clazz, id); - } - timeLog.log(start, "multiFindByCriteria<Business>(List>"); + timeLog.log(start, "findByCriteria(Varargs)"); return result; } - public <E extends BusinessEntity> E findByQuery( - Class<E> clazz, WikittyQuery criteria) { - long start = TimeLog.getTime(); - E result = null; - if (criteria != null) { - List<E> criterias = findByQuery(clazz, Collections.singletonList(criteria)); - if (!criterias.isEmpty()) { - result = criterias.get(0); - } - } - timeLog.log(start, "findByCriteria<Business>(One)"); - return result; - } - - public <E extends BusinessEntity> E[] findByQuery( - Class<E> clazz, WikittyQuery c1, WikittyQuery c2, WikittyQuery... otherCriteria) { - long start = TimeLog.getTime(); - - List<WikittyQuery> criterias = new ArrayList<WikittyQuery>(otherCriteria.length + 2); - Collections.addAll(criterias, c1, c2); - Collections.addAll(criterias, otherCriteria); - - List<E> resultList = findByQuery(clazz, criterias); - E[] result = resultList.toArray((E[])Array.newInstance(clazz, resultList.size())); - - timeLog.log(start, "findByCriteria<Business>(Varargs)"); - return result; - } - /////////////////////////////////////////////////////////////////////////// // - // FIND BY CRITERIA <Wikitty> - // - /////////////////////////////////////////////////////////////////////////// - - public List<Wikitty> findByQuery(List<WikittyQuery> criteria) { - long start = TimeLog.getTime(); - List<Wikitty> result = null; - if (criteria != null) { - List<String> id = findIdByQuery(criteria); - result = restore(id); - } - timeLog.log(start, "findByCriteria(List)"); - return result; - } - - public Wikitty findByQuery(WikittyQuery criteria) { - long start = TimeLog.getTime(); - String id = findIdByQuery(criteria); - Wikitty wikitty = restore(id); - timeLog.log(start, "findByCriteria(One)"); - return wikitty; - } - - public Wikitty[] findByQuery( - WikittyQuery c1, WikittyQuery c2, WikittyQuery... otherCriteria) { - long start = TimeLog.getTime(); - - List<WikittyQuery> criterias = new ArrayList<WikittyQuery>(otherCriteria.length + 2); - Collections.addAll(criterias, c1, c2); - Collections.addAll(criterias, otherCriteria); - - List<String> resultList = findIdByQuery(criterias); - List<Wikitty> wikitties = restore(resultList); - Wikitty[] result = wikitties.toArray(new Wikitty[resultList.size()]); - - timeLog.log(start, "findByCriteria(Varargs)"); - return result; - } - - - /////////////////////////////////////////////////////////////////////////// - // // FIND BY TREE NODE // /////////////////////////////////////////////////////////////////////////// @@ -1325,7 +1272,7 @@ .eq(WikittyGroup.FQ_FIELD_WIKITTYGROUP_NAME, groupName) .end(); - Wikitty group = findByQuery(criteria); + Wikitty group = findByQuery(Wikitty.class, criteria); if (group != null && user != null) { result = WikittySecurityUtil.isMember(wikittyService, securityToken, @@ -1361,7 +1308,7 @@ * * @param queryResult result to convert * @param target to cast into. - * Can be Wikitty, BusinessEntity, String, Date, BigDecimal, Boolean, byte[] + * Can be Wikitty, BusinessEntity, String, Date, Number (returned is BigDecimal), Boolean, byte[] * @return new WikittyQueryResult with element in right class or Exception * if conversion is impossible */ @@ -1401,7 +1348,7 @@ // on commence par tout mettre en Wikitty, en utilisant le if du dessus WikittyQueryResult<Wikitty> resultTmp = castTo(Wikitty.class, queryResult); castedResult = (List<E>)WikittyUtil.newInstance((Class<BusinessEntity>)target, resultTmp.getAll()); - } else if (target.isAssignableFrom(BigDecimal.class)) { + } else if (target.isAssignableFrom(Number.class)) { castedResult = new ArrayList<E>(queryResult.size()); for (Object o : queryResult) { BigDecimal v = WikittyUtil.toBigDecimal(o); @@ -1448,6 +1395,4 @@ return result; } - - } Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQuery.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQuery.java 2011-12-30 15:50:02 UTC (rev 1270) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQuery.java 2011-12-31 14:06:23 UTC (rev 1271) @@ -42,12 +42,6 @@ /** query condition */ protected Condition condition; - /** - * Use to return select ids - * Be carefull, can be long if many result is found - */ - protected String select; - /** First index to get result. */ protected int first = 0; /** Number of result to retrieve. 100 by default. */ @@ -114,7 +108,7 @@ result = ObjectUtils.equals(this.getName(), other.getName()) && ObjectUtils.equals(this.getFirst(), other.getFirst()) && ObjectUtils.equals(this.getLimit(), other.getLimit()) && - ObjectUtils.equals(this.getSelect(), other.getSelect()) && + ObjectUtils.equals(this.isFacetExtension(), other.isFacetExtension()) && ObjectUtils.equals(this.getFacetField(), other.getFacetField()) && ObjectUtils.equals(this.getSortAscending(), other.getSortAscending()) && ObjectUtils.equals(this.getSortDescending(), other.getSortDescending()) && @@ -170,15 +164,6 @@ return this; } - public String getSelect() { - return select; - } - - public WikittyQuery setSelect(String select) { - this.select = select; - return this; - } - public int getFirst() { return first; } Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryMaker.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryMaker.java 2011-12-30 15:50:02 UTC (rev 1270) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryMaker.java 2011-12-31 14:06:23 UTC (rev 1271) @@ -37,6 +37,7 @@ import org.nuiton.wikitty.query.conditions.NotNull; import org.nuiton.wikitty.query.conditions.Null; import org.nuiton.wikitty.query.conditions.Or; +import org.nuiton.wikitty.query.conditions.Select; import org.nuiton.wikitty.query.conditions.True; import org.nuiton.wikitty.query.conditions.Unlike; @@ -850,10 +851,29 @@ } /** + * Add {@link Select}, this condition must be first or + * @param element le champs dont il faut extraire les donnees + * @return {@code this} + * @see {@link Select} + */ + public WikittyQueryMaker select(String element) { + return select(new ElementField(element)); + } + + /* + * @see {@link Select} + */ + public WikittyQueryMaker select(ElementField element) { + Condition child = new Select(element); + addOnStack(child); + return this; + } + + /** * Add {@link In} to allow search on association (like sql join). * To close this sub query you must used {@link #close()} * @param foreignFieldName association fieldName - * @return sub query + * @return {@code this} * @see {@link In} */ public WikittyQueryMaker in(String foreignFieldName) { Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryParser.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryParser.java 2011-12-30 15:50:02 UTC (rev 1270) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryParser.java 2011-12-31 14:06:23 UTC (rev 1271) @@ -30,6 +30,7 @@ import org.nuiton.wikitty.query.conditions.In; import org.nuiton.wikitty.query.conditions.NotNull; import org.nuiton.wikitty.query.conditions.Null; +import org.nuiton.wikitty.query.conditions.Select; import org.nuiton.wikitty.query.conditions.True; import org.nuiton.wikitty.query.conditions.Unlike; import org.parboiled.BaseParser; @@ -65,6 +66,8 @@ public static final String FALSE = "FALSE"; public static final String ID = "id"; + public static final String SELECT = "SELECT"; + public static final String WHERE = "WHERE"; public static final String IN = "IN"; public static final String LITERAL_CLOSE = "\""; public static final String LITERAL_OPEN = "\""; @@ -181,15 +184,14 @@ Rule Parens() { return Sequence(space(), BRACKET_OPEN, space(), or(), space(), BRACKET_CLOSE, space()); - // FIXME } Rule condition() { return FirstOf( - not(), isNull(), isNotNull(), + not(), isNull(), isNotNull(), select(), eq(), neq(), less(), lesseq(), greater(), greatereq(), like(), notlike(), between(), containsAll(), containsOne(), - associated(), rTrue(), rFalse(), keyword() + in(), rTrue(), rFalse(), keyword() ); } @@ -278,10 +280,14 @@ value(), elems.get().add(removeQuote(match())), space()), CURLY_BRACKET_CLOSE, push(new ContainsOne(toElement(pop().toString()), elems.get()))); } - Rule associated() { + Rule in() { return Sequence(field(), push(match()), space(), IN, space(), term(), - push(new In(toElement(pop().toString()), (Condition)pop()))); + push(new In(toElement(pop(1).toString()), (Condition)pop()))); } + Rule select() { + return Sequence(SELECT, space(), field(), push(match()), space(), WHERE, space(), term(), + push(new Select(new ElementField(pop(1).toString()), (Condition)pop()))); + } Rule keyword() { return Sequence(value(), push(new Keyword(removeQuote(match())))); } Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryVisitor.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryVisitor.java 2011-12-30 15:50:02 UTC (rev 1270) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryVisitor.java 2011-12-31 14:06:23 UTC (rev 1271) @@ -22,6 +22,7 @@ import org.nuiton.wikitty.query.conditions.NotNull; import org.nuiton.wikitty.query.conditions.Null; import org.nuiton.wikitty.query.conditions.Or; +import org.nuiton.wikitty.query.conditions.Select; import org.nuiton.wikitty.query.conditions.True; import org.nuiton.wikitty.query.conditions.Unlike; @@ -126,6 +127,25 @@ * @param o * @return True if we want visit sub-element, otherwize false */ + /** + * True if we want visit sub-element, otherwize false + * @param o + * @return True if we want visit sub-element, otherwize false + */ + abstract public boolean visitEnter(Select o); + /** + * Leave method is alway called, but evaluation of enter is passed in + * arguement + * + * @param o + * @param enterOrMiddleResult result returned by visitEnter method + */ + abstract public void visitLeave(Select o, boolean enterOrMiddleResult); + /** + * True if we want visit sub-element, otherwize false + * @param o + * @return True if we want visit sub-element, otherwize false + */ abstract public boolean visitEnter(Not o); /** * Leave method is alway called, but evaluation of enter is passed in Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryVisitorCopy.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryVisitorCopy.java 2011-12-30 15:50:02 UTC (rev 1270) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryVisitorCopy.java 2011-12-31 14:06:23 UTC (rev 1271) @@ -23,6 +23,7 @@ import org.nuiton.wikitty.query.conditions.NotNull; import org.nuiton.wikitty.query.conditions.Null; import org.nuiton.wikitty.query.conditions.Or; +import org.nuiton.wikitty.query.conditions.Select; import org.nuiton.wikitty.query.conditions.True; import org.nuiton.wikitty.query.conditions.Unlike; @@ -71,7 +72,6 @@ q.setFirst(o.getFirst()); q.setLimit(o.getLimit()); q.setName(o.getName()); - q.setSelect(o.getSelect()); q.setSortAscending(new ArrayList<ElementField>(o.getSortAscending())); q.setSortDescending(new ArrayList<ElementField>(o.getSortDescending())); @@ -121,6 +121,17 @@ } @Override + public boolean visitEnter(Select o) { + getQueryMaker().select(o.getElement()); + return true; + } + + @Override + public void visitLeave(Select o, boolean enterOrMiddleResult) { + getQueryMaker().close(); + } + + @Override public boolean visitEnter(In o) { getQueryMaker().in(o.getElement()); return true; Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryVisitorToString.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryVisitorToString.java 2011-12-30 15:50:02 UTC (rev 1270) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryVisitorToString.java 2011-12-31 14:06:23 UTC (rev 1271) @@ -20,6 +20,7 @@ import org.nuiton.wikitty.query.conditions.NotNull; import org.nuiton.wikitty.query.conditions.Null; import org.nuiton.wikitty.query.conditions.Or; +import org.nuiton.wikitty.query.conditions.Select; import org.nuiton.wikitty.query.conditions.True; import org.nuiton.wikitty.query.conditions.Unlike; @@ -89,6 +90,18 @@ } @Override + public boolean visitEnter(Select o) { + text += WikittyQueryParser.SELECT + o.getElement().getValue() + + WikittyQueryParser.WHERE + WikittyQueryParser.BRACKET_OPEN; + return true; + } + + @Override + public void visitLeave(Select o, boolean enterOrMiddleResult) { + text += WikittyQueryParser.BRACKET_CLOSE; + } + + @Override public boolean visitEnter(In o) { text += o.getElement().getValue() + WikittyQueryParser.IN + WikittyQueryParser.BRACKET_OPEN; return true; Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions/Condition.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions/Condition.java 2011-12-30 15:50:02 UTC (rev 1270) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions/Condition.java 2011-12-31 14:06:23 UTC (rev 1271) @@ -1,6 +1,9 @@ package org.nuiton.wikitty.query.conditions; import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; +import org.apache.commons.lang.ClassUtils; import org.nuiton.wikitty.WikittyException; import org.nuiton.wikitty.query.WikittyQueryVisitor; import org.nuiton.wikitty.query.WikittyQueryVisitorToString; @@ -29,13 +32,57 @@ } /** + * Retourne la liste des conditions qui ne peuvent pas etre ajoutee + * a cette condition. + * Lorsqu'on implante un fils il est preferable de faire une nouvelle + * collection dans lequel on ajout ou on retire des elements + * <pre> + * return new Set(super.rejectedCondition).add/remove(condition.class) + * </pre> + * car certain regle sont mises pour toutes + * les conditions comme l'interdiction d'ajouter un Select. + * + * @param c + */ + public Set<Class<? extends Condition>> rejectedCondition() { + Set<Class<? extends Condition>> result = new HashSet<Class<? extends Condition>>(); + result.add(Select.class); + return result; + } + + public void checkAddCondition(Condition c) { + Class clazz = null; + if (c != null) { + clazz = c.getClass(); + } + + Set<?> rejected = rejectedCondition(); + if (rejected == null) { + // tout est rejete + throw new WikittyException(String.format( + "Add condition is not allowed in this condition type '%s'", + getClass().getSimpleName())); + } else if (rejected.contains(clazz)) { + throw new WikittyException(String.format( + "Add condition '%s' is not allowed in this condition type '%s'", + ClassUtils.getShortCanonicalName(c, "null"), + getClass().getSimpleName())); + } + } + + /** * For non terminal condition this method add subCondition. * For terminal this method must return an exception + * + * When you overriden this method, you must call {@link #checkAddCondition} + * in first * * @param c */ public void addCondition(Condition c) { - throw new WikittyException("Add condition is not allowed in this condition type"); + throw new WikittyException(String.format( + "Add condition is not allowed in this condition type '%s'", + getClass().getSimpleName())); } public void accept(WikittyQueryVisitor visitor) { Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions/ConditionNary.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions/ConditionNary.java 2011-12-30 15:50:02 UTC (rev 1270) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions/ConditionNary.java 2011-12-31 14:06:23 UTC (rev 1271) @@ -80,7 +80,10 @@ @Override public void addCondition(Condition c) { - getConditions().add(c); + if (c != null) { + checkAddCondition(c); + getConditions().add(c); + } } Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions/ConditionUnary.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions/ConditionUnary.java 2011-12-30 15:50:02 UTC (rev 1270) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions/ConditionUnary.java 2011-12-31 14:06:23 UTC (rev 1271) @@ -32,10 +32,13 @@ @Override public void addCondition(Condition c) { + checkAddCondition(c); if (subCondition == null) { this.subCondition = c; } else { - throw new WikittyException("ConditionUnary ("+getClass().getSimpleName()+") can't have more than one condition"); + throw new WikittyException(String.format( + "ConditionUnary (%s) can't have more than one condition", + getClass().getSimpleName())); } } Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions/In.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions/In.java 2011-12-30 15:50:02 UTC (rev 1270) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions/In.java 2011-12-31 14:06:23 UTC (rev 1271) @@ -1,5 +1,7 @@ package org.nuiton.wikitty.query.conditions; +import java.util.HashSet; +import java.util.Set; import org.apache.commons.lang.ObjectUtils; /** @@ -32,7 +34,20 @@ super(restriction); this.element = element; } - + + /** + * Le In autorise le Select + * @return + */ + @Override + public Set<Class<? extends Condition>> rejectedCondition() { + Set<Class<? extends Condition>> result = + new HashSet<Class<? extends Condition>>(super.rejectedCondition()); + // le in autorise le Select + result.remove(Select.class); + return result; + } + public Element getElement() { return element; } Added: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions/Select.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions/Select.java (rev 0) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/conditions/Select.java 2011-12-31 14:06:23 UTC (rev 1271) @@ -0,0 +1,54 @@ +package org.nuiton.wikitty.query.conditions; + +import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Cette condition n'accept pas d'etre utilise dans une autre condition. + * Il sert a demander l'extraction d'un autre champs que l'id. Si la valeur + * du champs est retrouvee plusieurs fois, cette valeur n'apparaitra qu'une + * seule fois dans les resultats (comme 'DISTINCT' en SQL) + * <p> + * Il y a donc deux types d'utilisation possible + * + * <pre> + * SELECT extName.fieldName WHERE condition + * condition ... IN (SELECT extName.fieldName WHERE other condition) + * </pre> + * + * @author poussin + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +public class Select extends ConditionUnary { + + private static final long serialVersionUID = 1L; + + protected ElementField element; + + public Select(ElementField element) { + this.element = element; + } + + public Select(ElementField element, Condition restriction) { + super(restriction); + this.element = element; + } + + public ElementField getElement() { + return element; + } + + @Override + boolean equalsDeep(Object other) { + boolean result = super.equalsDeep(other); + if (result) { + In op = (In)other; + result = ObjectUtils.equals(this.getElement(), op.getElement()); + } + return result; + } +} Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/storage/WikittySearchEngine.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/storage/WikittySearchEngine.java 2011-12-30 15:50:02 UTC (rev 1270) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/storage/WikittySearchEngine.java 2011-12-31 14:06:23 UTC (rev 1271) @@ -79,7 +79,10 @@ public PagedResult<String> findAllByCriteria(WikittyTransaction transaction, Criteria criteria); /** - * Find all wikitties that satisfy queries constraint + * Find all values that satisfy queries constraint. Values is Wikitty's id + * if there is no Select condition, otherwize is String that represent + * field value and can be String representation of + * Wikitty, Date, Boolean, Numeric, Binary, String * * @param transaction * @param queries Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/storage/WikittySearchEngineInMemory.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/storage/WikittySearchEngineInMemory.java 2011-12-30 15:50:02 UTC (rev 1270) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/storage/WikittySearchEngineInMemory.java 2011-12-31 14:06:23 UTC (rev 1271) @@ -60,12 +60,12 @@ import org.nuiton.wikitty.query.conditions.Equals; import org.nuiton.wikitty.query.conditions.Greater; import org.nuiton.wikitty.query.conditions.GreaterOrEquals; -import org.nuiton.wikitty.query.conditions.Join; import org.nuiton.wikitty.query.conditions.Less; import org.nuiton.wikitty.query.conditions.LessOrEquals; import org.nuiton.wikitty.query.conditions.Like; import org.nuiton.wikitty.query.conditions.NotEquals; import org.nuiton.wikitty.query.conditions.NotNull; +import org.nuiton.wikitty.query.conditions.Select; import org.nuiton.wikitty.query.conditions.Unlike; import org.nuiton.wikitty.search.Criteria; import org.nuiton.wikitty.search.PagedResult; @@ -756,13 +756,24 @@ } @Override - public boolean visitEnter(Join o) { + public boolean visitEnter(Select o) { + // do nothing + return true; + } + + @Override + public void visitLeave(Select o, boolean enterOrMiddleResult) { + // do nothing + } + + @Override + public boolean visitEnter(org.nuiton.wikitty.query.conditions.In o) { boolean evalResult = false; String fqfieldName = o.getElement().getValue(); -// Object fieldValue = w.getFqField(fqfieldName); - // il faut que le champs exist et que la valeur soit un String (pas null) - if (w.hasField(fqfieldName) && (w.getFieldType(fqfieldName).getType() == TYPE.WIKITTY)) { + // il faut que le champs exist, mais tout type de champs convient + // maintenant qu'il est possible de faire un select + if (w.hasField(fqfieldName)) { //Get sub-restriction Condition sub = o.getSubCondition(); @@ -777,7 +788,6 @@ //Check that my field is contained in the sub-restriction results. evalResult = check(ContainsOnePredicate, o.getElement(), associatedList); -// associatedList.contains(String.valueOf(fieldValue)); } evalStack.push(evalResult); @@ -787,7 +797,7 @@ } @Override - public void visitLeave(Join o, boolean enterOrMiddleResult) { + public void visitLeave(org.nuiton.wikitty.query.conditions.In o, boolean enterOrMiddleResult) { // nothing to do } Modified: trunk/wikitty-api/src/test/java/org/nuiton/wikitty/storage/WikittySearchEngineInMemoryTest.java =================================================================== --- trunk/wikitty-api/src/test/java/org/nuiton/wikitty/storage/WikittySearchEngineInMemoryTest.java 2011-12-30 15:50:02 UTC (rev 1270) +++ trunk/wikitty-api/src/test/java/org/nuiton/wikitty/storage/WikittySearchEngineInMemoryTest.java 2011-12-31 14:06:23 UTC (rev 1271) @@ -132,7 +132,7 @@ { // test join WikittyQuery q = new WikittyQueryMaker() - .join(WikittyGroup.FQ_FIELD_WIKITTYGROUP_MEMBERS) + .in(WikittyGroup.FQ_FIELD_WIKITTYGROUP_MEMBERS) .eq(WikittyLabel.FQ_FIELD_WIKITTYLABEL_LABELS, "titi") .end(); WikittyQueryResult<String> result = se.findAllByQuery(null, q); @@ -146,7 +146,8 @@ WikittyQuery q = new WikittyQueryMaker() .or() .ideq(g2.getWikittyId()) - .join(WikittyGroup.FQ_FIELD_WIKITTYGROUP_MEMBERS).eq(WikittyLabel.FQ_FIELD_WIKITTYLABEL_LABELS, "titi") + .in(WikittyGroup.FQ_FIELD_WIKITTYGROUP_MEMBERS) + .eq(WikittyLabel.FQ_FIELD_WIKITTYLABEL_LABELS, "titi") .end(); WikittyQueryResult<String> result = se.findAllByQuery(null, q); // g1, g2, g3 doivent etre retrouve (g2 via ideq, et g1, g3 via le join) @@ -159,7 +160,8 @@ WikittyQuery q = new WikittyQueryMaker() .and() .not().ideq(g1.getWikittyId()).close() - .join(WikittyGroup.FQ_FIELD_WIKITTYGROUP_MEMBERS).eq(WikittyLabel.FQ_FIELD_WIKITTYLABEL_LABELS, "titi") + .in(WikittyGroup.FQ_FIELD_WIKITTYGROUP_MEMBERS) + .eq(WikittyLabel.FQ_FIELD_WIKITTYLABEL_LABELS, "titi") .end(); WikittyQueryResult<String> result = se.findAllByQuery(null, q); // g3 doit etre retrouve via le join, et g1 est exclue via la not(ideq) Modified: trunk/wikitty-solr/src/main/java/org/nuiton/wikitty/storage/solr/WikittyQueryVisitorToSolr.java =================================================================== --- trunk/wikitty-solr/src/main/java/org/nuiton/wikitty/storage/solr/WikittyQueryVisitorToSolr.java 2011-12-30 15:50:02 UTC (rev 1270) +++ trunk/wikitty-solr/src/main/java/org/nuiton/wikitty/storage/solr/WikittyQueryVisitorToSolr.java 2011-12-31 14:06:23 UTC (rev 1271) @@ -27,6 +27,7 @@ import org.nuiton.wikitty.query.conditions.NotNull; import org.nuiton.wikitty.query.conditions.Null; import org.nuiton.wikitty.query.conditions.Or; +import org.nuiton.wikitty.query.conditions.Select; import org.nuiton.wikitty.query.conditions.True; import org.nuiton.wikitty.query.conditions.Unlike; import org.nuiton.wikitty.services.WikittyTransaction; @@ -128,6 +129,18 @@ } @Override + public boolean visitEnter(Select o) { + // nothing to do + // select is done in WikittySearchEngineSolr method + return true; + } + + @Override + public void visitLeave(Select o, boolean enterOrMiddleResult) { + // nothing to do + } + + @Override public boolean visitEnter(In o) { WikittyQuery q = new WikittyQuery(o.getSubCondition()).setLimit(Integer.MAX_VALUE); WikittyQueryResult<String> result = solrServer.findAllByQuery(tx, q); Modified: trunk/wikitty-solr/src/main/java/org/nuiton/wikitty/storage/solr/WikittySearchEngineSolr.java =================================================================== --- trunk/wikitty-solr/src/main/java/org/nuiton/wikitty/storage/solr/WikittySearchEngineSolr.java 2011-12-30 15:50:02 UTC (rev 1270) +++ trunk/wikitty-solr/src/main/java/org/nuiton/wikitty/storage/solr/WikittySearchEngineSolr.java 2011-12-31 14:06:23 UTC (rev 1271) @@ -66,6 +66,7 @@ import org.nuiton.util.TimeLog; import org.nuiton.wikitty.WikittyConfigOption; import org.nuiton.wikitty.WikittyUtil; +import org.nuiton.wikitty.entities.WikittyExtension; import org.nuiton.wikitty.entities.WikittyTreeNodeHelper; import org.nuiton.wikitty.query.FacetQuery; import org.nuiton.wikitty.query.FacetTopic; @@ -74,6 +75,7 @@ import org.nuiton.wikitty.query.WikittyQueryResult; import org.nuiton.wikitty.query.WikittyQueryResultTreeNode; import org.nuiton.wikitty.query.conditions.ElementField; +import org.nuiton.wikitty.query.conditions.Select; import org.nuiton.wikitty.search.Search; import org.nuiton.wikitty.search.TreeNodeResult; @@ -657,162 +659,181 @@ @Override public WikittyQueryResult<String> findAllByQuery(WikittyTransaction transaction, WikittyQuery query) { try { - // Create querySolr - WikittyQueryVisitorToSolr v = new WikittyQueryVisitorToSolr( - transaction, this, elementModifier); - query.getCondition().accept(v); - String queryString = v.getSolrQuery(); - SolrQuery querySolr = new SolrQuery(SOLR_QUERY_PARSER + queryString); + WikittyQueryResult<String> result; - // Add paged - int first = query.getFirst(); - int limit = query.getLimit(); + if (query.getCondition() instanceof Select) { + // gere les conditions qui commence par select + // il faut recreer deux query, une pour le select, une pour les facettes s'il y en a + // car le select est execute via une facette, mais cette facette + // n'a pas les meme limites que les autres facette - if (limit == Integer.MAX_VALUE) { - // WARNING It is necessary to substract 'start' otherwise, - // there is a capacity overlow in solR - limit = Integer.MAX_VALUE - first; - } - querySolr.setStart(first); - querySolr.setRows(limit); + Select select = (Select)query.getCondition(); + String extName = WikittyExtension.extractExtensionName( + select.getElement().getValue()); + WikittyQueryMaker newCond = new WikittyQueryMaker() + .and() + .exteq(extName) + .condition(select.getSubCondition()); - // Add sorting - List<ElementField> sortAscending = query.getSortAscending(); - if(sortAscending != null) { - for (ElementField sort : sortAscending) { - String tranform = elementModifier.convertToSolr(transaction, sort); - tranform += WikittySolrConstant.SUFFIX_SORTABLE; - querySolr.addSortField(tranform, SolrQuery.ORDER.asc); - } - } - - List<ElementField> sortDescending = query.getSortDescending(); - if(sortDescending != null) { - for (ElementField sort : sortDescending) { - String tranform = elementModifier.convertToSolr(transaction, sort); - tranform += WikittySolrConstant.SUFFIX_SORTABLE; - querySolr.addSortField(tranform, SolrQuery.ORDER.desc); - } - } + // copy de la query pour les facettes + WikittyQuery queryFacet = query.copy(); + queryFacet.setCondition(newCond.getCondition()); + queryFacet.setLimit(0); - // task : #1785 Add select method to allow specify wikittyId return field - // If select is not empty, add facet on field - String select = query.getSelect(); - boolean hasSelect = StringUtils.isNotEmpty(select); - if (hasSelect) { + // copy de la query pour le select + // on part de facet qui a deja la bonne condition + WikittyQuery querySelect = queryFacet.copy(); + querySelect.setLimit(0); + querySelect.setFacetMinCount(0); + querySelect.setFacetLimit(Integer.MAX_VALUE); + querySelect.setFacetQuery(); + querySelect.setFacetField(select.getElement()); - // Limit on wikitty - String selectWikitty = SolrUtil.getSolrFieldName(select, TYPE.WIKITTY); - query.addFacetField(new ElementField(selectWikitty)); + // execution des requetes + WikittyQueryResult<String> resultFacet = findAllByQuery(transaction, queryFacet); + WikittyQueryResult<String> resultSelect = findAllByQuery(transaction, querySelect); - // We need no result, just facet - query.setLimit(0); - } + // creation des resultats via la facette select + List<FacetTopic> topics = resultSelect.getFacets().get(select.getElement().getValue()); - // Add faceting - boolean isFacetExtension = query.isFacetExtension(); - List<ElementField> facetField = query.getFacetField(); - List<FacetQuery> facetQuery = query.getFacetQuery(); + List<String> selectList = new ArrayList<String>( + Math.min(topics.size(), query.getLimit())); + if (query.getFirst() < topics.size()) { + int first = query.getFirst(); + int last = Math.min(topics.size(), query.getFirst() + query.getLimit()); + for (FacetTopic topic : topics.subList(first, last)) { + selectList.add(topic.getTopicName()); + } + } - // use to map query string to criteria facet name - Map<String, String> facetQueryToName = new HashMap<String, String>(); + // fusion des resultats + result = new WikittyQueryResult<String>( + query.getName(), + query.getFirst(), + topics.size(), + resultSelect.getQueryString(), + resultFacet.getFacets(), + selectList); + } else { - if (isFacetExtension - || CollectionUtils.isNotEmpty(facetField) - || CollectionUtils.isNotEmpty(facetQuery)) { - querySolr.setFacet(true); - querySolr.setFacetMinCount(query.getFacetMinCount()); - querySolr.setFacetLimit(query.getFacetLimit()); + // Create querySolr + WikittyQueryVisitorToSolr v = new WikittyQueryVisitorToSolr( + transaction, this, elementModifier); + query.getCondition().accept(v); + String queryString = v.getSolrQuery(); + SolrQuery querySolr = new SolrQuery(SOLR_QUERY_PARSER + queryString); - if (isFacetExtension) { - querySolr.addFacetField(WikittySolrConstant.SOLR_EXTENSIONS); + // Add paged + int first = query.getFirst(); + int limit = query.getLimit(); + + if (limit == Integer.MAX_VALUE) { + // WARNING It is necessary to substract 'start' otherwise, + // there is a capacity overlow in solR + limit = Integer.MAX_VALUE - first; } + querySolr.setStart(first); + querySolr.setRows(limit); - // field facetisation - if (facetField != null) { - for (ElementField fqfieldName : facetField) { - String tranform = elementModifier.convertToSolr(transaction, fqfieldName); - querySolr.addFacetField(tranform); + // Add sorting + List<ElementField> sortAscending = query.getSortAscending(); + if(sortAscending != null) { + for (ElementField sort : sortAscending) { + String tranform = elementModifier.convertToSolr(transaction, sort); + tranform += WikittySolrConstant.SUFFIX_SORTABLE; + querySolr.addSortField(tranform, SolrQuery.ORDER.asc); } } - // query facetisation - if (facetQuery != null) { - for (FacetQuery facet : facetQuery) { - v = new WikittyQueryVisitorToSolr( - transaction, this, elementModifier); - facet.getCondition().accept(v); - String queryFacet = v.getSolrQuery(); - facetQueryToName.put(queryFacet, facet.getName()); - querySolr.addFacetQuery(queryFacet); + List<ElementField> sortDescending = query.getSortDescending(); + if(sortDescending != null) { + for (ElementField sort : sortDescending) { + String tranform = elementModifier.convertToSolr(transaction, sort); + tranform += WikittySolrConstant.SUFFIX_SORTABLE; + querySolr.addSortField(tranform, SolrQuery.ORDER.desc); } } - } - QueryResponse resp = SolrUtil.executeQuery(solrServer, querySolr); - SolrDocumentList solrResults = resp.getResults(); + // Add faceting + boolean isFacetExtension = query.isFacetExtension(); + List<ElementField> facetField = query.getFacetField(); + List<FacetQuery> facetQuery = query.getFacetQuery(); - Map<String, List<FacetTopic>> facets = new HashMap<String, List<FacetTopic>>(); + // use to map query string to criteria facet name + Map<String, String> facetQueryToName = new HashMap<String, String>(); - // la facet sur les extensions est directement et convenablement - // gere comme un champs - if (CollectionUtils.isNotEmpty(facetField)) { - for (FacetField facet : resp.getFacetFields()) { - String facetName = elementModifier.convertToField(facet.getName()); - List<FacetTopic> topics = new ArrayList<FacetTopic>(); - if (facet.getValues() != null) { - for (FacetField.Count value : facet.getValues()) { - String topicName = value.getName(); - int topicCount = (int) value.getCount(); - FacetTopic topic = new FacetTopic(facetName, topicName, topicCount); - topics.add(topic); + if (isFacetExtension + || CollectionUtils.isNotEmpty(facetField) + || CollectionUtils.isNotEmpty(facetQuery)) { + querySolr.setFacet(true); + querySolr.setFacetMinCount(query.getFacetMinCount()); + querySolr.setFacetLimit(query.getFacetLimit()); + + if (isFacetExtension) { + querySolr.addFacetField(WikittySolrConstant.SOLR_EXTENSIONS); + } + + // field facetisation + if (facetField != null) { + for (ElementField fqfieldName : facetField) { + String tranform = elementModifier.convertToSolr(transaction, fqfieldName); + querySolr.addFacetField(tranform); } } - facets.put(facetName, topics); - } - } - if (CollectionUtils.isNotEmpty(facetQuery)) { - for (Map.Entry<String, Integer> facet : resp.getFacetQuery().entrySet()) { - String facetName = facet.getKey(); - // don't use contains because, map can have key with null value - if (null != facetQueryToName.get(facetName)) { - facetName = facetQueryToName.get(facetName); + // query facetisation + if (facetQuery != null) { + for (FacetQuery facet : facetQuery) { + v = new WikittyQueryVisitorToSolr( + transaction, this, elementModifier); + facet.getCondition().accept(v); + String queryFacet = v.getSolrQuery(); + facetQueryToName.put(queryFacet, facet.getName()); + querySolr.addFacetQuery(queryFacet); + } } - Integer count = facet.getValue(); - List<FacetTopic> topics = new ArrayList<FacetTopic>(); - FacetTopic topic = new FacetTopic(facetName, facetName, count); - topics.add(topic); - facets.put(facetName, topics); } - } - List<String> ids; - int numFound; - if (hasSelect) { + QueryResponse resp = SolrUtil.executeQuery(solrServer, querySolr); + SolrDocumentList solrResults = resp.getResults(); - // Get select facet - List<FacetTopic> facetTopics = facets.get(select); + Map<String, List<FacetTopic>> facets = new HashMap<String, List<FacetTopic>>(); - // Remove this one - facets.remove(select); + // la facet sur les extensions est directement et convenablement + // gere comme un champs + if (CollectionUtils.isNotEmpty(facetField)) { + for (FacetField facet : resp.getFacetFields()) { + String facetName = elementModifier.convertToField(facet.getName()); + List<FacetTopic> topics = new ArrayList<FacetTopic>(); + if (facet.getValues() != null) { + for (FacetField.Count value : facet.getValues()) { + String topicName = value.getName(); + int topicCount = (int) value.getCount(); + FacetTopic topic = new FacetTopic(facetName, topicName, topicCount); + topics.add(topic); + } + } + facets.put(facetName, topics); + } + } - // Total found - numFound = facetTopics.size(); - - // Extract ids starting on firstIndex - ids = new ArrayList<String>(); - - // If all must be return, use limit - for (int i = first;i <= limit && i < numFound; i++) { - FacetTopic topic = facetTopics.get(i); - ids.add(topic.getTopicName()); + if (CollectionUtils.isNotEmpty(facetQuery)) { + for (Map.Entry<String, Integer> facet : resp.getFacetQuery().entrySet()) { + String facetName = facet.getKey(); + // don't use contains because, map can have key with null value + if (null != facetQueryToName.get(facetName)) { + facetName = facetQueryToName.get(facetName); + } + Integer count = facet.getValue(); + List<FacetTopic> topics = new ArrayList<FacetTopic>(); + FacetTopic topic = new FacetTopic(facetName, facetName, count); + topics.add(topic); + facets.put(facetName, topics); + } } - } else { - // Extract ids - ids = new ArrayList<String>(solrResults.size()); + List<String> ids = new ArrayList<String>(solrResults.size()); for (SolrDocument doc : solrResults) { String id = SolrUtil.getStringFieldValue(doc, SOLR_ID); @@ -820,14 +841,14 @@ } // Get total num found - numFound = (int)resp.getResults().getNumFound(); - } + int numFound = (int)resp.getResults().getNumFound(); - // Build paged result - WikittyQueryResult<String> result = new WikittyQueryResult<String>( - query.getName(), - first, numFound, queryString, facets, ids); + // Build paged result + result = new WikittyQueryResult<String>( + query.getName(), + first, numFound, queryString, facets, ids); + } return result; } catch (SolrServerException eee) { throw new WikittyException(String.format( Added: trunk/wikitty-solr/src/test/java/org/nuiton/wikitty/storage/solr/WikittySearchEngineSolrForQueryTest.java =================================================================== --- trunk/wikitty-solr/src/test/java/org/nuiton/wikitty/storage/solr/WikittySearchEngineSolrForQueryTest.java (rev 0) +++ trunk/wikitty-solr/src/test/java/org/nuiton/wikitty/storage/solr/WikittySearchEngineSolrForQueryTest.java 2011-12-31 14:06:23 UTC (rev 1271) @@ -0,0 +1,97 @@ +package org.nuiton.wikitty.storage.solr; + +import java.util.List; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.nuiton.util.ApplicationConfig; +import org.nuiton.wikitty.WikittyClient; +import org.nuiton.wikitty.WikittyConfig; +import org.nuiton.wikitty.entities.WikittyGroup; +import org.nuiton.wikitty.entities.WikittyGroupImpl; +import org.nuiton.wikitty.entities.WikittyImpl; +import org.nuiton.wikitty.entities.WikittyLabel; +import org.nuiton.wikitty.entities.WikittyLabelImpl; +import org.nuiton.wikitty.query.WikittyQuery; +import org.nuiton.wikitty.query.WikittyQueryMaker; +import org.nuiton.wikitty.query.WikittyQueryResult; +import org.nuiton.wikitty.query.conditions.Element; + +/** + * + * @author poussin + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +public class WikittySearchEngineSolrForQueryTest { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(WikittySearchEngineSolrForQueryTest.class); + + protected static WikittyServiceSolr ws; + + protected static ApplicationConfig instance = + WikittyConfig.getConfig("wikitty-config-sample-inmemory.properties"); + + protected WikittyClient client = new WikittyClient(ws); + + @Before + public void deleteAll() throws Exception { + ws.clear(null); + } + + @BeforeClass + public static void initTests() throws Exception { + + SolrTestHelper.initTests(instance); + + ws = new WikittyServiceSolr(instance); + } + + @Test + public void testSelect() throws Exception { + // for id for easy debugging + WikittyImpl w = new WikittyImpl("g1"); + WikittyGroupImpl g1 = new WikittyGroupImpl(w); + g1.setName("Group1"); + w = new WikittyImpl("g2"); + WikittyGroupImpl g2 = new WikittyGroupImpl(w); + g2.setName("GROUP2"); + + w = new WikittyImpl("l1"); + WikittyLabelImpl l1 = new WikittyLabelImpl(w); + l1.addLabels(g1.getName()); + + client.store(g1, g2, l1); + + { + WikittyQuery query = new WikittyQueryMaker() + .select(WikittyGroup.FQ_FIELD_WIKITTYGROUP_NAME) + .end(); + + WikittyQueryResult<String> result = client.findAllByQuery(query); + + System.out.println(result.getAll()); + Assert.assertEquals(2, result.getTotalResult()); + } + + { + WikittyQuery query = new WikittyQueryMaker() + .and() + .exteq(WikittyGroup.EXT_WIKITTYGROUP) + .in(WikittyGroup.FQ_FIELD_WIKITTYGROUP_NAME) + .select(WikittyLabel.FQ_FIELD_WIKITTYLABEL_LABELS) + .end(); + + WikittyQueryResult<String> result = client.findAllByQuery(query); + + System.out.println(result.getAll()); + Assert.assertEquals(1, result.getTotalResult()); + } + } +}
participants (1)
-
bpoussin@users.nuiton.org