r129 - in trunk: . chorem-web/src/main/java/org/chorem/action chorem-web/src/main/resources chorem-web/src/main/webapp/WEB-INF/jsp/bonzoms
Author: bpoussin Date: 2011-11-08 18:46:52 +0100 (Tue, 08 Nov 2011) New Revision: 129 Url: http://chorem.org/repositories/revision/chorem/129 Log: EntitySearchJson permet d'afficher des aggregation de wikitty dans un tableau Tableau des companies fonctionnel avec la recherche fulltext (suite a modif implantation association dans wikitty) Modified: trunk/chorem-web/src/main/java/org/chorem/action/EntitySearchJsonAction.java trunk/chorem-web/src/main/resources/struts.xml trunk/chorem-web/src/main/webapp/WEB-INF/jsp/bonzoms/companies.jsp trunk/chorem-web/src/main/webapp/WEB-INF/jsp/bonzoms/persons.jsp trunk/pom.xml Modified: trunk/chorem-web/src/main/java/org/chorem/action/EntitySearchJsonAction.java =================================================================== --- trunk/chorem-web/src/main/java/org/chorem/action/EntitySearchJsonAction.java 2011-11-06 17:01:34 UTC (rev 128) +++ trunk/chorem-web/src/main/java/org/chorem/action/EntitySearchJsonAction.java 2011-11-08 17:46:52 UTC (rev 129) @@ -1,9 +1,15 @@ package org.chorem.action; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import net.sf.json.JSONSerializer; @@ -12,6 +18,9 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts2.interceptor.ParameterAware; +import org.nuiton.wikitty.entities.FieldType; +import org.nuiton.wikitty.entities.Wikitty; +import org.nuiton.wikitty.entities.WikittyExtension; import org.nuiton.wikitty.search.Criteria; import org.nuiton.wikitty.search.PagedResult; import org.nuiton.wikitty.search.Search; @@ -52,12 +61,25 @@ // All Record protected int records = 0; - protected List gridModel; + protected List<Wikitty> wikitties; + protected List<Map<String, Object>> gridModel; + + /** la liste des extensions que doit avoir les objets recherchés*/ protected String wikittyExtension; + /** + * la liste des lien entre wikitty qu'il faut charger + * exemple: "Employee.person,Employee.company" + */ + protected String wikittyLinkToLoad; + protected Set<String> wikittyLinkToLoadCache; + /** la recherche fulltext a faire sur les objets de base (pas les liens) pour les filtrer*/ protected String fulltextSearch = ""; + /** Recherche multi-critere en syntaxe json + * exemple: {"groupOp":"OR","rules":[{"field":"Person.lastName","op":"eq","data":"coq"},{"field":"Person.lastName","op":"ne","data":"Poussin"},{"field":"Person.firstName","op":"eq","data":"benjamin"}]} + */ protected String filters; /** action faite via le grid ['add', 'edit', 'del'], si vide alors une simple recherche */ @@ -67,6 +89,10 @@ protected Map<String, String[]> parameters; + public void setWikittyLinkToLoad(String wikittyLinkToLoad) { + this.wikittyLinkToLoad = wikittyLinkToLoad; + } + public void setParameters(Map<String, String[]> parameters) { this.parameters = parameters; } @@ -106,8 +132,8 @@ this.total = total; } - public List getGridModel() { - return gridModel; + public List getWikitties() { + return wikitties; } public String execute() { try { @@ -117,18 +143,22 @@ } } - Class clazz = Class.forName(wikittyExtension); - Search search = Search.query(); + if (StringUtils.isNotBlank(wikittyExtension)) { + Collection<String> col = toCollection(wikittyExtension); + search.exteq(col); + } + if (StringUtils.isNotBlank(filters)) { JSONObject jsonFilter = (JSONObject) JSONSerializer.toJSON( filters ); String groupOp = jsonFilter.getString("groupOp"); log.debug("groupOp: " + groupOp); + Search filter; if ("or".equalsIgnoreCase(groupOp)) { - search = search.or(); + filter = search.or(); } else { - search = search.and(); + filter = search.and(); } JSONArray rules = jsonFilter.getJSONArray("rules"); int rulesCount = JSONArray.getDimensions(rules)[0]; @@ -137,7 +167,7 @@ String field = rule.getString("field"); String op = rule.getString("op"); String data = rule.getString("data"); - addCondition(search, field, op, data); + addCondition(filter, field, op, data); } } else if (StringUtils.isNotBlank(fulltextSearch)) { @@ -145,7 +175,12 @@ String s = "*" + fulltextSearch + "*"; // TODO poussin 20111106: voir pourquoi like fontion comme on souhaite et pas Keyword :( // keyword ne fonctionne pas avec les * - search.like("#fulltext", s); + Search or = search.or(); + or = or.like("#fulltext", s); + log.debug("link: " + getWikittyLinkToLoadCache()); + for (String link:getWikittyLinkToLoadCache()) { + or.associated(link).like("#fulltext", s); + } } else { // si pas de filtre on recherche tout search.rTrue(); @@ -183,20 +218,78 @@ log.debug("criteria: " + criteria); } - PagedResult result = getChoremProxy().findAllByCriteria(clazz, criteria); + PagedResult<Wikitty> result = getChoremProxy().findAllByCriteria(criteria); - setGridModel(result.getAll()); + setWikitties(result.getAll()); + + if (log.isTraceEnabled()) { + log.trace("result: " + getWikitties()); + } + setRecords(result.getNumFound()); setTotal((int) Math.ceil((double) getRecords() / (double) getRows())); + gridModel = new ArrayList<Map<String, Object>>(); + for (Wikitty w:wikitties) { + Map<String, Object> map = wikittyToMap(w); + gridModel.add(map); + } + return SUCCESS; - } catch (ClassNotFoundException eee) { - log.error(String.format("Can't find class '%s'", wikittyExtension), eee); + } catch (Exception eee) { + log.error(String.format("Can't find wikitty '%s'", wikittyExtension), eee); throw new UnhandledException(eee); } } - public void setGridModel(List gridModel) { + protected Map<String, Object> wikittyToMap(Wikitty w) { + Map<String, Object> result = new HashMap<String, Object>(); + String wid = w.getId(); + + result.put("id", wid); + result.putAll(w.getFieldValue()); + for (String fieldToLoad:getWikittyLinkToLoadCache()) { + String linkId = (String)w.getFqField(fieldToLoad); + if (linkId != null) { + // TODO poussin 20111107 pas tres optimal de faire une requete a chaque besoin + // il faudrait collecter les ids, pour faire une seule demande pour tous + // mais tant que pour le deploiement, tout est sur le meme serveur + // si un peu moins genant + Wikitty wlink = getChoremProxy().restore(linkId); + Map<String, Object> map = wikittyToMap(wlink); + map.remove("id"); + result.putAll(map); + } + } + return result; + } + + protected void addToLoad(Map<String, List<String>> toLoad, String wid, String wfield) { + List<String> l = toLoad.get(wid); + if (l == null) { + l = new ArrayList<String>(); + toLoad.put(wid, l); + } + l.add(wfield); + } + + public Set<String> getWikittyLinkToLoadCache() { + if (wikittyLinkToLoadCache == null) { + wikittyLinkToLoadCache = + new HashSet<String>(toCollection(wikittyLinkToLoad)); + } + return wikittyLinkToLoadCache; + } + + public void setWikitties(List<Wikitty> wikitties) { + this.wikitties = wikitties; + } + + public List<Map<String, Object>> getGridModel() { + return gridModel; + } + + public void setGridModel(List<Map<String, Object>> gridModel) { this.gridModel = gridModel; } @@ -266,7 +359,7 @@ } else if ("nn".equalsIgnoreCase(op)) { search.isNotNull(field); } else { - Collection<String> col = Arrays.asList(StringUtils.split(data, " :,;|")); + Collection<String> col = toCollection(data); if ("in".equalsIgnoreCase(op)) { search.in(field, col); } else if ("ni".equalsIgnoreCase(op)) { @@ -277,4 +370,14 @@ } } + + protected Collection<String> toCollection(String s) { + Collection<String> result; + if (s == null) { + result = Collections.EMPTY_LIST; + } else { + result = Arrays.asList(StringUtils.split(s, " :,;|")); + } + return result; + } } Modified: trunk/chorem-web/src/main/resources/struts.xml =================================================================== --- trunk/chorem-web/src/main/resources/struts.xml 2011-11-06 17:01:34 UTC (rev 128) +++ trunk/chorem-web/src/main/resources/struts.xml 2011-11-08 17:46:52 UTC (rev 129) @@ -21,6 +21,18 @@ <package name="publicArea" extends="struts-default"> <result-types> <result-type name="json" class="org.apache.struts2.json.JSONResult"/> + <result-type name="wikitty-json" class="org.apache.struts2.json.JSONResult"> + <param name="includeProperties"> + fulltextSearch, + page, + sord, + sidx, + rows, + records, + total, + gridModel.* + </param> + </result-type> </result-types> <interceptors> @@ -48,7 +60,7 @@ <result>/WEB-INF/jsp/home.jsp</result> </action> <action name="EntitySearchJson" class="org.chorem.action.EntitySearchJsonAction"> - <result type="json"/> + <result type="wikitty-json"/> </action> </package> Modified: trunk/chorem-web/src/main/webapp/WEB-INF/jsp/bonzoms/companies.jsp =================================================================== --- trunk/chorem-web/src/main/webapp/WEB-INF/jsp/bonzoms/companies.jsp 2011-11-06 17:01:34 UTC (rev 128) +++ trunk/chorem-web/src/main/webapp/WEB-INF/jsp/bonzoms/companies.jsp 2011-11-08 17:46:52 UTC (rev 129) @@ -18,35 +18,90 @@ <s:url id="companyDetails" namespace="/bonzoms" action="companyDetails"/> <script type="text/javascript"> function formatCompanyNameLink(cellvalue, options, rowObject) { - return "<a href='<s:property value="companyDetails"/>?companyId="+rowObject.wikittyId+"'>" + cellvalue + "</a>"; + return "<a href='<s:property value="companyDetails"/>?companyId="+rowObject['Employee.company']+"'>" + cellvalue + "</a>"; } </script> + <s:url id="personDetails" namespace="/bonzoms" action="personDetails"/> + <script type="text/javascript"> + function formatPersonNameLink(cellvalue, options, rowObject) { + return "<a href='<s:property value="personDetails"/>?personId="+rowObject['Employee.person']+"'>" + cellvalue + "</a>"; + } + </script> + + <%-- Partie generique (ou presque, ce ne sont que des variables qui change) --%> + + <s:url id="remoteurlFulltextSearch" namespace="/" action="EntitySearchJson" escapeAmp="false"> + <s:param name="wikittyExtension">Employee</s:param> + <s:param name="wikittyLinkToLoad">Employee.person,Employee.company</s:param> + </s:url> + + <s:url id="remoteurl" namespace="/" action="EntitySearchJson" escapeAmp="false"> + <s:param name="fulltextSearch"><%=StringUtils.defaultString(request.getParameter("fulltextSearch"))%></s:param> + <s:param name="wikittyExtension">Employee</s:param> + <s:param name="wikittyLinkToLoad">Employee.person,Employee.company</s:param> + </s:url> + + <script type="text/javascript"> + var timeoutHnd; + function doSearch() { + if(timeoutHnd) { + clearTimeout(timeoutHnd) + } + timeoutHnd = setTimeout(gridReload, 500) + } + + function gridReload() { + var filter = jQuery("#fulltextSearch").val(); + var gridUrl = "<s:property value="remoteurlFulltextSearch" escapeHtml="false"/>&fulltextSearch="+filter; + jQuery("#gridtable").jqGrid('setGridParam',{url:gridUrl,page:1}).trigger("reloadGrid"); + } + </script> + <s:form> - <s:textfield name="searchString"></s:textfield> + <s:textfield id="fulltextSearch" name="fulltextSearch" onkeydown="doSearch()"></s:textfield> <s:submit></s:submit> </s:form> - <s:url id="remoteurl" namespace="/" action="EntitySearchJson" escapeAmp="false"> - <s:param name="searchString"><%=StringUtils.defaultString(request.getParameter("searchString"))%></s:param> - <s:param name="wikittyExtension">org.chorem.entities.Company</s:param> + <s:url id="editurl" namespace="/" action="EntitySearchJson" escapeAmp="false"> </s:url> <sjg:grid id="gridtable" dataType="json" href="%{remoteurl}" - pager="true" gridModel="gridModel" rowList="10,20,50,100" rowNum="20" - rownumbers="false" + rownumbers="true" autowidth="true" - sortname="name" - sortorder="asc"> + sortname="Person.lastName" + sortorder="asc" + pager="true" + viewrecords="true" - <sjg:gridColumn name="name" title="Nom" formatter="formatCompanyNameLink"/> - <sjg:gridColumn name="type" title="Type"/> + multiselect="true" + + editurl="%{editurl}" + editinline="false" + + navigator="true" + navigatorAdd="true" + navigatorEdit="true" + navigatorDelete="true" + navigatorView="true" + navigatorSearch="true" + navigatorAddOptions="{height:280,reloadAfterSubmit:true}" + navigatorEditOptions="{height:280,reloadAfterSubmit:true}" + navigatorDeleteOptions="{height:280,reloadAfterSubmit:true}" + navigatorSearchOptions="{multipleGroup:true,showQuery:true,multipleSearch:true,sopt:['eq','ne','cn','nc','bw','bn','ew','en','lt','le','gt','ge','nu','nn','in','ni']}" + > + + <sjg:gridColumn name="id" hidden="true" key="true" title="id"/> + <sjg:gridColumn name="Company.name" index="Company.name" title="Société" formatter="formatCompanyNameLink"/> + <sjg:gridColumn name="Person.lastName" index="Person.lastName" title="Nom" editable="true" formatter="formatPersonNameLink"/> + <sjg:gridColumn name="Person.firstName" index="Person.firstName" title="Prénom" editable="true"/> + <sjg:gridColumn name="Employee.diploma" index="Employee.diploma" title="Diplôme"/> </sjg:grid> </body> Modified: trunk/chorem-web/src/main/webapp/WEB-INF/jsp/bonzoms/persons.jsp =================================================================== --- trunk/chorem-web/src/main/webapp/WEB-INF/jsp/bonzoms/persons.jsp 2011-11-06 17:01:34 UTC (rev 128) +++ trunk/chorem-web/src/main/webapp/WEB-INF/jsp/bonzoms/persons.jsp 2011-11-08 17:46:52 UTC (rev 129) @@ -15,22 +15,26 @@ <body> <h2><s:text name="chorem.bonzoms.persons" /></h2> + <s:url id="personDetails" namespace="/bonzoms" action="personDetails"/> + + <script type="text/javascript"> + function formatPersonNameLink(cellvalue, options, rowObject) { + return "<a href='<s:property value="personDetails"/>?personId="+rowObject.id+"'>" + cellvalue + "</a>"; + } + </script> + + + <s:url id="remoteurlFulltextSearch" namespace="/" action="EntitySearchJson" escapeAmp="false"> - <s:param name="wikittyExtension">org.chorem.entities.Person</s:param> + <s:param name="wikittyExtension">Person</s:param> </s:url> <s:url id="remoteurl" namespace="/" action="EntitySearchJson" escapeAmp="false"> <s:param name="fulltextSearch"><%=StringUtils.defaultString(request.getParameter("fulltextSearch"))%></s:param> - <s:param name="wikittyExtension">org.chorem.entities.Person</s:param> + <s:param name="wikittyExtension">Person</s:param> </s:url> - <s:url id="personDetails" namespace="/bonzoms" action="personDetails"/> - <script type="text/javascript"> - function formatPersonNameLink(cellvalue, options, rowObject) { - return "<a href='<s:property value="personDetails"/>?personId="+rowObject.wikittyId+"'>" + cellvalue + "</a>"; - } - var timeoutHnd; function doSearch() { if(timeoutHnd) { @@ -68,12 +72,8 @@ pager="true" viewrecords="true" - filter="true" multiselect="true" - footerrow="true" - userDataOnFooter="{'Person.lastName':'titi', firsName:'Toto'}" - editurl="%{editurl}" editinline="false" @@ -89,9 +89,9 @@ navigatorSearchOptions="{multipleSearch:true,sopt:['eq','ne','cn','nc','bw','bn','ew','en','lt','le','gt','ge','nu','nn','in','ni']}" > - <sjg:gridColumn name="wikittyId" hidden="true" key="true" title="id"/> - <sjg:gridColumn href="%{personDetails}" name="lastName" index="Person.lastName" title="Nom" editable="true" formatter="formatPersonNameLink"/> - <sjg:gridColumn name="firstName" index="Person.firstName" title="Prénom" editable="true"/> + <sjg:gridColumn name="id" hidden="true" key="true" title="id"/> + <sjg:gridColumn name="Person.lastName" index="Person.lastName" title="Nom" editable="true" formatter="formatPersonNameLink"/> + <sjg:gridColumn name="Person.firstName" index="Person.firstName" title="Prénom" editable="true"/> </sjg:grid> </body> Modified: trunk/pom.xml =================================================================== --- trunk/pom.xml 2011-11-06 17:01:34 UTC (rev 128) +++ trunk/pom.xml 2011-11-08 17:46:52 UTC (rev 129) @@ -56,7 +56,7 @@ <platform>chorem.org</platform> <projectId>chorem</projectId> - <eugenePluginVersion>2.3.2</eugenePluginVersion> + <eugenePluginVersion>2.4.1-SNAPSHOT</eugenePluginVersion> <nuitonUtilsVersion>2.3</nuitonUtilsVersion> <nuitonWebVersion>1.3</nuitonWebVersion> <nuitonI18nVersion>2.3.1</nuitonI18nVersion>
participants (1)
-
bpoussin@users.chorem.org