/******************************************************************************* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *******************************************************************************/ package org.apache.ofbiz.widget.renderer; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import org.apache.commons.collections4.MapUtils; import org.apache.ofbiz.base.util.Debug; import org.apache.ofbiz.base.util.UtilGenerics; import org.apache.ofbiz.base.util.UtilProperties; import org.apache.ofbiz.base.util.UtilValidate; import org.apache.ofbiz.base.util.collections.PagedList; import org.apache.ofbiz.entity.GenericEntityException; import org.apache.ofbiz.entity.util.EntityListIterator; import org.apache.ofbiz.widget.WidgetWorker; import org.apache.ofbiz.widget.model.ModelForm; /** * Utility methods for handling list pagination. * */ public final class Paginator { public static final String module = Paginator.class.getName(); public static int getActualPageSize(Map<String, Object> context) { Integer value = (Integer) context.get("actualPageSize"); return value != null ? value.intValue() : (getHighIndex(context) - getLowIndex(context)); } public static int getHighIndex(Map<String, Object> context) { Integer value = (Integer) context.get("highIndex"); return value != null ? value.intValue() : 0; } public static void getListLimits(ModelForm modelForm, Map<String, Object> context, Object entryList) { int viewIndex = 0; int viewSize = 0; int lowIndex = 0; int highIndex = 0; int listSize = modelForm.getOverrideListSize(context); if (listSize > 0) { //setOverridenListSize(true); } else if (entryList instanceof EntityListIterator) { EntityListIterator iter = (EntityListIterator) entryList; try { listSize = iter.getResultsSizeAfterPartialList(); } catch (GenericEntityException e) { Debug.logError(e, "Error getting list size", module); listSize = 0; } } else if (entryList instanceof List<?>) { List<?> items = (List<?>) entryList; listSize = items.size(); if(context.containsKey("result")){ Map<String, Object> resultMap = UtilGenerics.checkMap(context.get("result")); if(resultMap.containsKey("listSize")){ listSize = (int)resultMap.get("listSize"); } } } else if (entryList instanceof PagedList) { PagedList<?> pagedList = (PagedList<?>) entryList; listSize = pagedList.getSize(); } if (modelForm.getPaginate(context)) { viewIndex = getViewIndex(modelForm, context); viewSize = getViewSize(modelForm, context); lowIndex = viewIndex * viewSize; highIndex = (viewIndex + 1) * viewSize; } else { viewIndex = 0; viewSize = ModelForm.MAX_PAGE_SIZE; lowIndex = 0; highIndex = ModelForm.MAX_PAGE_SIZE; } context.put("listSize", Integer.valueOf(listSize)); context.put("viewIndex", Integer.valueOf(viewIndex)); context.put("viewSize", Integer.valueOf(viewSize)); context.put("lowIndex", Integer.valueOf(lowIndex)); context.put("highIndex", Integer.valueOf(highIndex)); } public static int getListSize(Map<String, Object> context) { Integer value = (Integer) context.get("listSize"); return value != null ? value.intValue() : 0; } public static int getLowIndex(Map<String, Object> context) { Integer value = (Integer) context.get("lowIndex"); return value != null ? value.intValue() : 0; } public static int getViewIndex(ModelForm modelForm, Map<String, Object> context) { String field = modelForm.getMultiPaginateIndexField(context); int viewIndex = 0; try { Object value = context.get(field); if (value == null) { // try parameters.VIEW_INDEX as that is an old OFBiz convention Map<String, Object> parameters = UtilGenerics.cast(context.get("parameters")); if (parameters != null) { value = parameters.get("VIEW_INDEX" + "_" + WidgetWorker.getPaginatorNumber(context)); if (value == null) { value = parameters.get(field); } } } // try paginate index field without paginator number if (value == null) { field = modelForm.getPaginateIndexField(context); value = context.get(field); } if (value instanceof Integer) { viewIndex = ((Integer) value).intValue(); } else if (value instanceof String) { viewIndex = Integer.parseInt((String) value); } } catch (Exception e) { Debug.logWarning(e, "Error getting paginate view index: " + e.toString(), module); } return viewIndex; } public static int getViewSize(ModelForm modelForm, Map<String, Object> context) { String field = modelForm.getMultiPaginateSizeField(context); int viewSize = modelForm.getDefaultViewSize(); try { Object value = context.get(field); if (value == null) { // try parameters.VIEW_SIZE as that is an old OFBiz convention Map<String, Object> parameters = UtilGenerics.cast(context.get("parameters")); if (parameters != null) { value = parameters.get("VIEW_SIZE" + "_" + WidgetWorker.getPaginatorNumber(context)); if (value == null) { value = parameters.get(field); } } } // try the page size field without paginator number if (value == null) { field = modelForm.getPaginateSizeField(context); value = context.get(field); } if (value instanceof Integer) { viewSize = ((Integer) value).intValue(); } else if (value instanceof String && UtilValidate.isNotEmpty(value)) { viewSize = Integer.parseInt((String) value); } } catch (Exception e) { Debug.logWarning(e, "Error getting paginate view size: " + e.toString(), module); } return viewSize; } public static void preparePager(ModelForm modelForm, Map<String, Object> context) { String lookupName = modelForm.getListName(); if (UtilValidate.isEmpty(lookupName)) { Debug.logError("No value for list or iterator name found.", module); return; } Object obj = context.get(lookupName); if (obj == null) { if (Debug.verboseOn()) Debug.logVerbose("No object for list or iterator name [" + lookupName + "] found, so not running pagination.", module); return; } // if list is empty, do not render rows Iterator<?> iter = null; if (obj instanceof Iterator<?>) { iter = (Iterator<?>) obj; } else if (obj instanceof List<?>) { iter = ((List<?>) obj).listIterator(); } else if (obj instanceof PagedList<?>) { iter = ((PagedList<?>) obj).iterator(); } // set low and high index getListLimits(modelForm, context, obj); int listSize = ((Integer) context.get("listSize")).intValue(); int lowIndex = ((Integer) context.get("lowIndex")).intValue(); int highIndex = ((Integer) context.get("highIndex")).intValue(); // Debug.logInfo("preparePager: low - high = " + lowIndex + " - " + highIndex, module); // we're passed a subset of the list, so use (0, viewSize) range if (modelForm.isOverridenListSize()) { lowIndex = 0; highIndex = ((Integer) context.get("viewSize")).intValue(); } if (iter == null) return; // count item rows int itemIndex = -1; Object item = safeNext(iter); while (item != null && itemIndex < highIndex) { itemIndex++; item = safeNext(iter); } // Debug.logInfo("preparePager: Found rows = " + itemIndex, module); // reduce the highIndex if number of items falls short if ((itemIndex + 1) < highIndex) { highIndex = itemIndex + 1; // if list size is overridden, use full listSize context.put("highIndex", Integer.valueOf(modelForm.isOverridenListSize() ? listSize : highIndex)); } context.put("actualPageSize", Integer.valueOf(highIndex - lowIndex)); if (iter instanceof EntityListIterator) { try { ((EntityListIterator) iter).beforeFirst(); } catch (GenericEntityException e) { Debug.logError(e, "Error rewinding list form render EntityListIterator: " + e.toString(), module); } } } private static <X> X safeNext(Iterator<X> iterator) { try { return iterator.next(); } catch (NoSuchElementException e) { return null; } } /** * @param context Map * @param viewIndexName * @return value of viewIndexName in context map (as an int) or return 0 as default */ public static Integer getViewIndex(final Map<String, ? extends Object> context, final String viewIndexName) { return getViewIndex(context, viewIndexName, 0); } /** * @param context * @param viewIndexName * @param defaultValue * @return value of viewIndexName in context map (as an int) or return defaultValue */ public static Integer getViewIndex(final Map<String, ? extends Object> context, final String viewIndexName, final int defaultValue) { return MapUtils.getInteger(context, viewIndexName, defaultValue); } /** * @param context * @param viewSizeName * @return value of viewSizeName in context map (as an int) or return * default value from widget.properties */ public static Integer getViewSize(Map<String, ? extends Object> context, String viewSizeName) { int defaultSize = UtilProperties.getPropertyAsInteger("widget", "widget.form.defaultViewSize", 20); if (context.containsKey(viewSizeName)) { return MapUtils.getInteger(context, viewSizeName, defaultSize); } return defaultSize; } }