details: https://code.openbravo.com/erp/devel/pi/rev/9bb00b5b71ad changeset: 35248:9bb00b5b71ad user: Asier Lostalé <asier.lostale <at> openbravo.com> date: Fri Dec 14 15:22:51 2018 +0100 summary: fixed bug 39644: P&E doesn't set selected records on top
In P&E selected records in UI were not set on top of non selected ones. Now they are sorted in backend, also we ensure that the whole selection is returned in the page even if it didn't originally fit on it. diffstat: modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/DataSourceUtils.java | 49 ++-- modules/org.openbravo.service.json/src/org/openbravo/service/json/AdvancedQueryBuilder.java | 4 + modules/org.openbravo.service.json/src/org/openbravo/service/json/DefaultJsonDataService.java | 101 +++++++++- 3 files changed, 122 insertions(+), 32 deletions(-) diffs (237 lines): diff -r 9f06f79b75a9 -r 9bb00b5b71ad modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/DataSourceUtils.java --- a/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/DataSourceUtils.java Mon Dec 17 12:54:18 2018 +0100 +++ b/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/DataSourceUtils.java Fri Dec 14 15:22:51 2018 +0100 @@ -18,19 +18,19 @@ */ package org.openbravo.service.datasource; -import java.util.ArrayList; -import java.util.List; +import java.util.Collections; +import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.commons.lang.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.codehaus.jettison.json.JSONArray; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import org.openbravo.dal.core.OBContext; import org.openbravo.service.json.JsonUtils; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.LogManager; /** * This class contains utility methods for dataSource related classes @@ -80,35 +80,36 @@ * according to that criteria. */ public static int getNumberOfSelectedRecords(Map<String, String> parameters) { - List<String> selectedRecords = new ArrayList<String>(); boolean hasCriteria = parameters.containsKey("criteria"); - if (hasCriteria) { - try { - selectedRecords = getSelectedRecordsFromCriteria(JsonUtils.buildCriteria(parameters)); - } catch (JSONException jsonex) { - log.error("Error retrieving number of selected records", jsonex); - } + if (!hasCriteria) { + return 0; } - return selectedRecords.size(); + return getSelectedRecordsFromCriteria(JsonUtils.buildCriteria(parameters)).size(); } /** - * Returns a list of selected record IDs from a criteria included in the JSONObject received as + * Returns a set of selected record IDs from a criteria included in the JSONObject received as * parameter. */ - public static List<String> getSelectedRecordsFromCriteria(JSONObject buildCriteria) - throws JSONException { - List<String> selectedRecords = new ArrayList<String>(); - JSONArray criteriaArray = buildCriteria.getJSONArray("criteria"); - for (int i = 0; i < criteriaArray.length(); i++) { - JSONObject criteria = criteriaArray.getJSONObject(i); - if (criteria.has("fieldName") && criteria.getString("fieldName").equals("id") - && criteria.has("value")) { - String value = criteria.getString("value"); - for (String recordId : value.split(",")) { - selectedRecords.add(recordId.trim()); + public static Set<String> getSelectedRecordsFromCriteria(JSONObject buildCriteria) { + if (buildCriteria == null) { + return Collections.emptySet(); + } + Set<String> selectedRecords = new HashSet<>(); + try { + JSONArray criteriaArray = buildCriteria.getJSONArray("criteria"); + for (int i = 0; i < criteriaArray.length(); i++) { + JSONObject criteria = criteriaArray.getJSONObject(i); + if (criteria.has("fieldName") && criteria.getString("fieldName").equals("id") + && criteria.has("value")) { + String value = criteria.getString("value"); + for (String recordId : value.split(",")) { + selectedRecords.add(recordId.trim()); + } } } + } catch (JSONException e) { + log.error("Error getting selected records from criteria {}", buildCriteria, e); } return selectedRecords; } diff -r 9f06f79b75a9 -r 9bb00b5b71ad modules/org.openbravo.service.json/src/org/openbravo/service/json/AdvancedQueryBuilder.java --- a/modules/org.openbravo.service.json/src/org/openbravo/service/json/AdvancedQueryBuilder.java Mon Dec 17 12:54:18 2018 +0100 +++ b/modules/org.openbravo.service.json/src/org/openbravo/service/json/AdvancedQueryBuilder.java Fri Dec 14 15:22:51 2018 +0100 @@ -1948,6 +1948,10 @@ public void setCriteria(JSONObject criteria) { this.criteria = criteria; + whereClause = null; + aliasIndex = 0; + orNesting = 0; + typedParameters = new ArrayList<>(); } public boolean isJoinAssociatedEntities() { diff -r 9f06f79b75a9 -r 9bb00b5b71ad modules/org.openbravo.service.json/src/org/openbravo/service/json/DefaultJsonDataService.java --- a/modules/org.openbravo.service.json/src/org/openbravo/service/json/DefaultJsonDataService.java Mon Dec 17 12:54:18 2018 +0100 +++ b/modules/org.openbravo.service.json/src/org/openbravo/service/json/DefaultJsonDataService.java Fri Dec 14 15:22:51 2018 +0100 @@ -18,6 +18,7 @@ */ package org.openbravo.service.json; +import static java.util.stream.Collectors.toList; import static org.openbravo.userinterface.selector.SelectorConstants.includeOrgFilter; import java.util.ArrayList; @@ -25,6 +26,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import javax.enterprise.inject.Any; import javax.enterprise.inject.Instance; @@ -253,13 +255,17 @@ // If the request is done from a P&E window, then we should adapt the page size to include // all selected records into the response - if (isPickAndEdit && shouldIncreasePageSize(parameters, bobs, startRowStr, endRowStr)) { - String newEndRow = Integer.toString(Integer.parseInt(endRowStr) - + JsonConstants.PAE_DATA_PAGE_SIZE); - parameters.put(JsonConstants.ENDROW_PARAMETER, newEndRow); - log.debug("The amount of selected records is higher than the page size, increasing page size to " - + newEndRow); - return fetch(parameters, filterOnReadableOrganizations); + if (isPickAndEdit) { + if (shouldIncreasePageSize(parameters, bobs, startRowStr, endRowStr)) { + String newEndRow = Integer.toString(Integer.parseInt(endRowStr) + + JsonConstants.PAE_DATA_PAGE_SIZE); + parameters.put(JsonConstants.ENDROW_PARAMETER, newEndRow); + log.debug("The amount of selected records is higher than the page size, increasing page size to " + + newEndRow); + return fetch(parameters, filterOnReadableOrganizations); + } + + bobs = getFixedPNESelection(queryService, bobs); } } @@ -272,7 +278,7 @@ count = bobs.size() + startRow; // computedMaxResults is one too much, if we got one to much then correct // the result and up the count so that the grid knows that there are more - if (bobs.size() == computedMaxResults) { + if (bobs.size() >= computedMaxResults) { bobs = bobs.subList(0, bobs.size() - 1); count++; } @@ -318,6 +324,85 @@ } /** + * Fixes selected records for P&E datasource requests ensuring all selected records are placed on + * top of not selected ones. If the complete selection was not initially fetched in current page, + * an additional query to retrieve it will be executed. + */ + private List<BaseOBObject> getFixedPNESelection(DataEntityQueryService queryService, + List<BaseOBObject> bobs) { + JSONObject criteria = queryService.getQueryBuilder().getCriteria(); + Set<String> selectedIds = DataSourceUtils.getSelectedRecordsFromCriteria(criteria); + if (selectedIds.isEmpty()) { + return bobs; + } + + List<BaseOBObject> selected = new ArrayList<>(bobs.size()); + List<BaseOBObject> unselected = new ArrayList<>(bobs.size()); + + for (BaseOBObject row : bobs) { + if (selectedIds.contains(row.getId())) { + selected.add(row); + } else { + unselected.add(row); + } + } + + int selectionInCurrentPage = selected.size(); + boolean completeSelectionInCurrentPage = selectionInCurrentPage == selectedIds.size(); + if (completeSelectionInCurrentPage) { + selected.addAll(unselected); + return selected; + } + + log.debug("P&E doesn't contain all selection, querying again to get it {}", criteria); + + List<BaseOBObject> gridRows = bobs; + try { + selected = getAllSelectedRecords(queryService, criteria); + int idsOutOfCurrentPage = selected.size() - selectionInCurrentPage; + selected.addAll(unselected); + + if (queryService.getFirstResult() > 0 && idsOutOfCurrentPage > 0) { + // fix pagination to prevent selection appearing in all pages + log.trace("Skipping {} rows for {}", idsOutOfCurrentPage, criteria); + gridRows = selected.stream().skip(idsOutOfCurrentPage).collect(toList()); + } else { + gridRows = selected; + } + } catch (JSONException e) { + log.error("failed selecting ids {}", criteria, e); + } + + return gridRows; + } + + /** Note side effect: criteria gets modified */ + private List<BaseOBObject> getAllSelectedRecords(DataEntityQueryService queryService, + JSONObject criteria) throws JSONException { + JSONArray criteriaFields = criteria.getJSONArray("criteria"); + JSONArray crieriaIdFields = new JSONArray(); + for (int i = 0; i < criteriaFields.length(); i++) { + JSONObject field = criteriaFields.getJSONObject(i); + if (field.has("fieldName") && "id".equals(field.getString("fieldName")) + && field.has("operator") && "equals".equals(field.getString("operator"))) { + crieriaIdFields.put(field); + } + } + log.trace("Old criteria {}", criteria); + criteria.put("criteria", crieriaIdFields); + + log.trace("New criteria {}", criteria); + + Integer originalFirstResult = queryService.getFirstResult(); + queryService.setCriteria(criteria); + queryService.setFirstResult(0); + queryService.setMaxResults(JsonConstants.PAE_MAX_PAGE_SIZE); + List<BaseOBObject> rows = queryService.list(); + queryService.setFirstResult(originalFirstResult); + return rows; + } + + /** * Used on requests received from pick and execute windows in order to avoid losing the selection. * It checks if the request has a criteria that contains the selected records. In that case, if * the amount of selected records is higher than the page size, then the end row is increased so _______________________________________________ Openbravo-commits mailing list Openbravo-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openbravo-commits