org.opentaps.common.event.PaginationEvents.java Source code

Java tutorial

Introduction

Here is the source code for org.opentaps.common.event.PaginationEvents.java

Source

/*
 * Copyright (c) Open Source Strategies, Inc.
 *
 * Opentaps is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Opentaps is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Opentaps.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.opentaps.common.event;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import javolution.util.*;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.entity.GenericDelegator;
import org.ofbiz.entity.GenericEntity;
import org.ofbiz.party.party.PartyHelper;
import org.opentaps.common.builder.ListBuilder;
import org.opentaps.common.builder.ListBuilderException;
import org.opentaps.common.pagination.PaginationState;
import org.opentaps.common.pagination.Paginator;
import org.opentaps.common.pagination.PaginatorFactory;
import org.opentaps.common.util.UtilCommon;
import org.opentaps.foundation.entity.EntityInterface;

/**
 * Events that interact with paginators to fetch pages, change the sort order,
 * and change the size of the viewport.
 */
public final class PaginationEvents {

    private PaginationEvents() {
    }

    private static final String MODULE = PaginationEvents.class.getName();

    /**
     * Catchall request for fetching pages. It accepts a paginatorName and an
     * action to perform.
     * @param request a <code>HttpServletRequest</code> value
     * @param response a <code>HttpServletResponse</code> value
     * @return a <code>String</code> value
     */
    public static String paginate(HttpServletRequest request, HttpServletResponse response) {
        List<?> page = FastList.newInstance();
        Paginator paginator = PaginatorFactory.getPaginator(request);
        String action = UtilCommon.getParameter(request, "action");
        String pageNumberString = UtilCommon.getParameter(request, "pageNumber");

        if (paginator != null) {
            try {
                if (pageNumberString != null) {
                    try {
                        long pageNumber = Long.parseLong(pageNumberString);
                        page = paginator.getPageNumber(pageNumber);
                    } catch (NumberFormatException e) {
                        Debug.logWarning("Failed to get page numer [" + pageNumberString + "] to to format error: "
                                + e.getMessage(), MODULE);
                        page = paginator.getCurrentPage();
                    }
                } else if (action == null || "getCurrentPage".equals(action)) {
                    page = paginator.getCurrentPage();
                } else if ("getNextPage".equals(action)) {
                    page = paginator.getNextPage();
                } else if ("getPreviousPage".equals(action)) {
                    page = paginator.getPreviousPage();
                } else if ("getFirstPage".equals(action)) {
                    page = paginator.getFirstPage();
                } else if ("getLastPage".equals(action)) {
                    page = paginator.getLastPage();
                } else {
                    Debug.logWarning("Paginate action [" + action + "] not supported.", MODULE);
                    page = paginator.getCurrentPage();
                }
            } catch (ListBuilderException e) {
                return doListBuilderExceptionResponse(request, response, paginator, e);
            }
        }
        return doPaginationResponse(request, response, paginator, page);
    }

    /**
     * Changes the paginator order by.
     * @param request a <code>HttpServletRequest</code> value
     * @param response a <code>HttpServletResponse</code> value
     * @return a <code>String</code> value
     */
    public static String changePaginationOrder(HttpServletRequest request, HttpServletResponse response) {
        List<?> page = FastList.newInstance();
        Paginator paginator = PaginatorFactory.getPaginator(request);
        if (paginator != null) {
            String orderByString = UtilCommon.getParameter(request, "orderBy");
            String orderByReverseString = UtilCommon.getParameter(request, "orderByReverse");
            List<String> orderBy = PaginationState.loadOrderBy(orderByString);
            List<String> orderByReverse = PaginationState.loadOrderBy(orderByReverseString);

            if (orderByReverse == null) {
                paginator.changeOrderBy(orderBy);
            } else {
                paginator.changeOrderBy(orderBy, orderByReverse);
            }
            try {
                page = paginator.getCurrentPage();
            } catch (ListBuilderException e) {
                return doListBuilderExceptionResponse(request, response, paginator, e);
            }
        }
        return doPaginationResponse(request, response, paginator, page);
    }

    /**
     * Changes the paginator view size.
     * @param request a <code>HttpServletRequest</code> value
     * @param response a <code>HttpServletResponse</code> value
     * @return a <code>String</code> value
     */
    public static String changePaginationViewSize(HttpServletRequest request, HttpServletResponse response) {
        List<?> page = FastList.newInstance();
        Paginator paginator = PaginatorFactory.getPaginator(request);
        if (paginator != null) {
            long delta = 0;
            long size = 0;
            String deltaValue = UtilCommon.getParameter(request, "delta");
            String newSize = UtilCommon.getParameter(request, "newSize");
            String toggleViewAll = UtilCommon.getParameter(request, "toggleViewAll");
            if (deltaValue != null) {
                try {
                    delta = Long.parseLong(deltaValue);
                } catch (NumberFormatException e) {
                    Debug.logError(e, e.getMessage(), MODULE);
                }
                if (delta != 0) {
                    paginator.changeViewSize(delta);
                }
            } else if (newSize != null) {
                try {
                    size = Long.parseLong(newSize);
                } catch (NumberFormatException e) {
                    Debug.logError(e, e.getMessage(), MODULE);
                }
                if (size != 0) {
                    paginator.setViewSize(size);
                }
            } else if (toggleViewAll != null) {
                paginator.toggleViewAll();
            }

            try {
                page = paginator.getCurrentPage();
            } catch (ListBuilderException e) {
                return doListBuilderExceptionResponse(request, response, paginator, e);
            }
        }
        return doPaginationResponse(request, response, paginator, page);
    }

    /**
     * Decides whether to do a JSON response or set the values in the request
     * attributes for formlets.
     * @param request a <code>HttpServletRequest</code> value
     * @param response a <code>HttpServletResponse</code> value
     * @param paginator a <code>Paginator</code> value
     * @param page a <code>List</code> value
     * @return a <code>String</code> value
     */
    public static String doPaginationResponse(HttpServletRequest request, HttpServletResponse response,
            Paginator paginator, List<?> page) {
        if (paginator == null) {
            return "success"; // Formlet event handler will deal with this
        }
        if (paginator.isFormlet()) {
            return doPaginationResponseFormlet(request, paginator, page);
        } else {
            return doPaginationResponseJSON(response, paginator, page);
        }
    }

    /**
     * Builds a JSONObject response string with the following parameters:
     *
     * <ul>
     * <li><b>page:</b> JSONArray containing the page to render.</li>
     * <li><b>pageNumber:</b> The page number.</li>
     * <li><b>totalPages:</b> Total pages in the list.</li>
     * <li><b>viewSize:</b> The size of the viewport.</li>
     * </ul>
     * @param response a <code>HttpServletResponse</code> value
     * @param paginator a <code>Paginator</code> value
     * @param page a <code>List</code> value
     * @return a <code>String</code> value
     */
    public static String doPaginationResponseJSON(HttpServletResponse response, Paginator paginator, List<?> page) {
        JSONObject map = new JSONObject();
        map.put("pageRows", JSONArray.fromObject(page).toString());
        if (paginator != null) {
            map.put("pageNumber", new Long(paginator.getPageNumber()));
            map.put("totalPages", new Long(paginator.getTotalPages()));
            map.put("viewSize", new Long(paginator.getViewSize()));
        }
        return AjaxEvents.doJSONResponse(response, map);
    }

    /**
     * Stores result data in the request attributes for the formlet.
     *
     * Other data about the paginator and context are put in the template
     * context by FormletEventHandler, therefore we only care to return
     * information about the actual list of data.
     * @param request a <code>HttpServletRequest</code> value
     * @param paginator a <code>Paginator</code> value
     * @param page a <code>List</code> value
     * @return a <code>String</code> value
     */
    public static String doPaginationResponseFormlet(HttpServletRequest request, Paginator paginator,
            List<?> page) {
        request.setAttribute("pageRows", page);
        return "success";
    }

    // when the pagination crashes due to some list building error, such as bad
    // code in a bsh closure, we note this and let FormletEventHandler decide
    // what to do
    private static String doListBuilderExceptionResponse(HttpServletRequest request, HttpServletResponse response,
            Paginator paginator, ListBuilderException e) {
        request.setAttribute("listBuilderException", e); // save the exception
        return "listBuilderException"; // FormletEventHandler should check for this
    }

    /**
     * Export a paginated data list to Excel.
     *
     * @param request the servlet request
     * @param response servlet response
     * @return a String object that represents the process status
     */

    public static String renderPaginatedListAsExcel(HttpServletRequest request, HttpServletResponse response) {
        String strPaginatorName = request.getParameter("paginatorName");
        String strOpentapsApplicationName = request.getParameter("opentapsApplicationName");
        if (StringUtils.isEmpty(strPaginatorName)) {
            Debug.logError("The parameter [paginatorName] is missing in the request.", MODULE);
            return "error";
        }

        if (StringUtils.isEmpty(strOpentapsApplicationName)) {
            Debug.logError("The parameter [opentapsApplicationName] is missing in the request.", MODULE);
            return "error";
        }

        String retval = exportPaginatedListToExcel(strPaginatorName, strOpentapsApplicationName, request, response);

        return retval;
    }

    private static String exportPaginatedListToExcel(final String strPaginatorName,
            final String strOpentapsApplicationName, HttpServletRequest request, HttpServletResponse response) {
        GenericDelegator delegator = (GenericDelegator) request.getAttribute("delegator");
        Paginator paginator = PaginatorFactory.getPaginator(request.getSession(), strPaginatorName,
                strOpentapsApplicationName);
        if (paginator == null) {
            Debug.logError("Failed to retrieve the paginator [" + strPaginatorName + "] in the application ["
                    + strOpentapsApplicationName + "]", MODULE);
            return "error";
        }

        // paginator exists in session
        ListBuilder listBuilder = paginator.getListBuilder();
        if (listBuilder == null) {
            Debug.logError("Null list builder is found in the paginator [" + strPaginatorName
                    + "] in the application [" + strOpentapsApplicationName + "]", MODULE);
            return "error";
        }

        List dataList = null;
        try {
            dataList = listBuilder.getCompleteList();
        } catch (ListBuilderException lbe) {
            Debug.logError(
                    "ListBuilderException is caught while exporting the paginator [" + strPaginatorName
                            + "] in the application [" + strOpentapsApplicationName + "] : " + lbe.getMessage(),
                    MODULE);
            return "error";
        }

        if (dataList == null || dataList.isEmpty()) {
            Debug.logWarning("Empty data list is returned in the paginator [" + strPaginatorName
                    + "] in the application [" + strOpentapsApplicationName + "]", MODULE);
            return "error";
        }

        String entityName = null;
        if (UtilValidate.isNotEmpty(dataList)) {
            Object entity = dataList.get(0);
            if (entity instanceof GenericEntity) {
                entityName = ((GenericEntity) entity).getEntityName();
            }
        }

        // find the type of the List and convert to a List of Map
        List<Map<String, Object>> mapDataList = FastList.newInstance();
        if (UtilValidate.isNotEmpty(dataList)) {
            for (Object o : dataList) {
                if (o instanceof GenericEntity) {
                    // change GenericEntity object to normal Map
                    Map newMap = new FastMap();
                    newMap.putAll((GenericEntity) o);
                    mapDataList.add(newMap);
                } else if (o instanceof Map) {
                    mapDataList.add((Map<String, Object>) o);
                } else if (o instanceof EntityInterface) {
                    mapDataList.add(((EntityInterface) o).toMap());
                }
            }
        }

        // write the data list to Excel

        // get the field key list
        Map<String, Object> element = mapDataList.get(0);
        List<String> keys = new ArrayList<String>();
        if (element != null) {
            Set<String> keySet = element.keySet();
            for (String key : keySet) {
                if ("lastUpdatedStamp".equals(key) || "lastUpdatedTxStamp".equals(key) || "createdStamp".equals(key)
                        || "createdTxStamp".equals(key)) {
                    continue;
                }

                keys.add(key);
            }
        }

        if (UtilValidate.isNotEmpty(entityName) && "AcctgTransAndEntries".equals(entityName)) {
            for (Map<String, Object> mapData : mapDataList) {
                String partyId = (String) mapData.get("partyId");
                String partyName = partyId == null ? null : PartyHelper.getPartyName(delegator, partyId, true);
                mapData.put("partyName", partyName);
                String debitCreditFlag = (String) mapData.get("debitCreditFlag");
                BigDecimal amount = (BigDecimal) mapData.get("amount");
                BigDecimal debitAmount = "D".equals(debitCreditFlag) ? amount : null;
                BigDecimal creditAmount = "C".equals(debitCreditFlag) ? amount : null;
                mapData.put("debitAmount", debitAmount);
                mapData.put("creditAmount", creditAmount);
            }
            // Add a Party Name column after requires1099 column
            keys.add(keys.indexOf("requires1099"), "partyName");
            // remove first name/last name/group name columns in export excel
            keys.remove("firstName");
            keys.remove("lastName");
            keys.remove("groupName");
            // add debitAmount/creditAmount columns, remove debitCreditFlag/amount columns
            keys.add("debitAmount");
            keys.add("creditAmount");
            keys.remove("amount");
            keys.remove("debitCreditFlag");
        }

        if (keys.isEmpty()) {
            Debug.logError("Empty field name list is returned in the data list of paginator [" + strPaginatorName
                    + "] in the application [" + strOpentapsApplicationName + "]", MODULE);
            return "error";
        }

        // create a map for column header labels
        Map<String, Object> columnHeaderMap = new HashMap<String, Object>();
        for (String key : keys) {
            columnHeaderMap.put(key, key);
        }

        List<Map<String, Object>> excelDataList = new ArrayList<Map<String, Object>>();
        excelDataList.add(columnHeaderMap);
        excelDataList.addAll(mapDataList);

        // using random string as part of file name, avoid multi user operate in same time.
        String fileName = "data_" + String.valueOf((int) (Math.random() * 100000)) + ".xls";
        String excelFilePath = UtilCommon.getAbsoluteFilePath(request, fileName);
        try {
            UtilCommon.saveToExcel(excelFilePath, "data", keys, excelDataList);
        } catch (IOException ioe) {
            Debug.logError("IOException is thrown while trying to write to the Excel file: " + ioe.getMessage(),
                    MODULE);
            return "error";
        }

        return downloadExcel(fileName, request, response);
    }

    /**
     * Download an existing Excel file from the ${opentaps_home}/runtime/output
     * directory. The Excel file is deleted after the download.
     *
     * @param filename the file name String object
     * @param request a <code>HttpServletRequest</code> value
     * @param response a <code>HttpServletResponse</code> value
     * @return a <code>String</code> value
     */
    private static String downloadExcel(String filename, HttpServletRequest request, HttpServletResponse response) {
        File file = null;
        ServletOutputStream out = null;
        FileInputStream fileToDownload = null;

        try {
            out = response.getOutputStream();

            file = new File(UtilCommon.getAbsoluteFilePath(request, filename));
            fileToDownload = new FileInputStream(file);

            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment; filename=" + filename);
            response.setContentLength(fileToDownload.available());

            int c;
            while ((c = fileToDownload.read()) != -1) {
                out.write(c);
            }

            out.flush();
        } catch (FileNotFoundException e) {
            Debug.logError("Failed to open the file: " + filename, MODULE);
            return "error";
        } catch (IOException ioe) {
            Debug.logError("IOException is thrown while trying to download the Excel file: " + ioe.getMessage(),
                    MODULE);
            return "error";
        } finally {
            try {
                out.close();
                if (fileToDownload != null) {
                    fileToDownload.close();
                    // Delete the file under /runtime/output/ this is optional
                    file.delete();
                }
            } catch (IOException ioe) {
                Debug.logError("IOException is thrown while trying to download the Excel file: " + ioe.getMessage(),
                        MODULE);
                return "error";
            }
        }

        return "success";
    }

}