import oracle.xml.xsql.*; import oracle.xml.parser.v2.*; import org.w3c.dom.*; import java.net.*; import java.util.StringTokenizer; import java.sql.SQLException; public class Paging extends XSQLActionHandlerImpl { private static final String PAGE_PARAM_NAME = "p"; private static final String ROWSPERPAGE = "rows-per-page"; private static final String TARGETPAGEARGS = "url-params"; public void handleAction(Node root) throws SQLException { XSQLPageRequest req = getPageRequest(); Element actElt = getActionElement(); // Get the count query from the action element content String query = getActionElementContent(); // Get the number of rows per page, defaulting to 10 long pageSize = longVal(getAttributeAllowingParam(ROWSPERPAGE,actElt),10); long totalRows = longVal(firstColumnOfFirstRow(root,query),0); long curPage = longVal(variableValue(PAGE_PARAM_NAME,actElt),1); // Get the name of the current page to use as the target String pageName = curPageName(req); // Get any URL parameter names that need to be echoed into paging URL's String pageArgs = getAttributeAllowingParam(TARGETPAGEARGS,actElt); // Calculate the total number of pages long totalPages = totalRows / pageSize; long fract = totalRows % pageSize; if (fract > 0) totalPages++; // Make sure current page is between 1 < cur < totalPages if (curPage < 1) curPage = 1;if (curPage > totalPages) curPage = totalPages; // Create the <paging> fragment to add to the "data page" Document d = actElt.getOwnerDocument(); Element e = d.createElement("paging"); root.appendChild(e); addResultElement(e,"total-rows",Long.toString(totalRows)); addResultElement(e,"total-pages",Long.toString(totalPages)); addResultElement(e,"current-page",Long.toString(curPage)); if (curPage < totalPages) addResultElement(e,"next-page",Long.toString(curPage+1)); if (curPage > 1) addResultElement(e,"prev-page",Long.toString(curPage-1)); addResultElement(e,"target-page",pageName); if (pageArgs != null && !pageArgs.equals("")) addResultElement(e,"target-args",expandedUrlParams(pageArgs,actElt)); // Set to page-level parameters that the <xsql:query> can use req.setPageParam("paging-skip",Long.toString((curPage-1)*pageSize)); req.setPageParam("paging-max",Long.toString(pageSize)); } // Get the name of the current page from the current page's URI private String curPageName(XSQLPageRequest req) { String thisPage = req.getSourceDocumentURI();; int pos = thisPage.lastIndexOf('/'); if (pos >=0) thisPage = thisPage.substring(pos+1); pos = thisPage.indexOf('?'); if (pos >=0) thisPage = thisPage.substring(0,pos-1); return thisPage; } // Convert String to long with a default in case blank, null, or not a number private long longVal(String longstr, long def) { long val = def; try { if (longstr != null && !longstr.equals("")) val = Long.parseLong(longstr); } catch (NumberFormatException nfe) {} return val; } private String expandedUrlParams(String paramNameList,Element actElt) { // Allow comma-separate or space-separated name list paramNameList = paramNameList.replace(',',' '); StringTokenizer st = new StringTokenizer(paramNameList); StringBuffer paramString = new StringBuffer(); int tokens = 0; while (st.hasMoreTokens()) { String paramName = st.nextToken(); String paramValue = variableValue(paramName,actElt); if (++tokens > 1) { paramString.append("&"); } paramString.append(paramName) .append("=") .append(paramValue); } return paramString.toString(); } } |